I am pretty new to coq and I have so far managed to only prove things that are I can also prove by hand. So when I came across the Selection monad and decided to implement it in haskell, I thought it would be a good excercise but I got stuck. Could someone provide an example of a proof in coq that the selection monad is an applicative and a monad? Here is a haskell implementation of the functor.
newtype Sel r a = Sel { runSel :: (a -> r) -> a }
instance Functor (Sel r) where
fmap ab (Sel ara) = Sel (ab . ara . (. ab))
Extra thanks if you can also also prove the monad laws.
EDIT: Here is my proof that the functor exists:
Definition sel (R A : Type) := (A -> R) -> A.
Theorem functor_exists : forall (R A B : Type),
(A -> B) -> sel R A -> sel R B.
intros R A B. unfold sel. intros AB ARA BR.
apply AB. apply ARA. intro. apply BR. apply AB. exact X.
Qed.
You don't have to use tactics because it's Coq: you can use it as a programming language in a way that is fairly similar to Haskell.
First, because R is going to be a variable present all the time in this section, we can make the notations a bit lighter by mentioning it once and for all:
Section SelMon.
Variable (R : Type).
We can then replicate your definition of sel (without the R variable because it's already in context). And write fmap as a nice definition rather than a proof using tactics:
Definition sel (A : Type) := (A -> R) -> A.
Definition fmap {A B : Type} (f : A -> B) (s : sel A) : sel B :=
fun br => f (s (fun a => br (f a))).
The next step to prove that you have an applicative is to provide a pure method. Well it's easy enough: we can use a constant function.
Definition pure {A : Type} (a : A) : sel A :=
fun _ => a.
Then it gets a bit hairy. I'd advise you to start with join and then derive bind (and app from it) using the canonical constructions:
Definition join {A : Type} (ssa : sel (sel A)) : sel A.
Admitted.
Definition bind {A B : Type} (sa : sel A) (asb : A -> sel B) : sel B.
Admitted.
Definition app {A B : Type} (sab : sel (A -> B)) (sa : sel A) : sel B.
Admitted.
Once you're done with these, you can close the section and R will be added as a parameter to all of your definitions.
End SelMon.
Related
I'm wondering if there is a systematic way to interpret Coq Definitions as agda programs. I'm working through translating part of programming foundations and am not able to get the tUpdate function to work below. Why is this failing. The coq code is commented.
--Definition total_map (A : Type) := string -> A.
totalMap : Set → Set
totalMap A = String → A
-- Definition t_empty {A : Type} (v : A) : total_map A :=
-- (fun _ => v).
tEmpty : {A : Set} (v : A) → totalMap A
tEmpty = λ v x → v
-- Definition t_update {A : Type} (m : total_map A)
-- (x : string) (v : A) :=
-- fun x' => if eqb_string x x' then v else m x'.
tUpdate : {A : Set} (m : totalMap A) (x : String) (v : A) → Set
tUpdate m x v = λ x' → (if (x == x') then v else m x')
The lambda term produces the below error
(x' : String) → A !=< Set of type Set
when checking that the expression
λ x' → if x == x' then v else m x' has type Set
Is this a correct general schema for doing this translation, e.g., is this translation sound and complete?
Edit:
I realized update was supposed to return a map, but i'm confused as it coq can seemingly infer this while agda can't? I'd still welcome a more general answer to the latter question.
tUpdate : {A : Set} (m : totalMap A) (x : String) (v : A) → totalMap A
tUpdate m x v = λ x' → (if (x == x') then v else m x')
Coq and Agda are both based on very roughly the same dependent type theory, so in theory it would be possible to take the proof term generated by a Coq script and translate it into an Agda program. However, there are many small (and not so small) differences, e.g. Coq's impredicative Prop, cumulativity, differences in the termination checkers, ect, that would make such a translation difficult or impossible.
However, what you're asking for here isn't really an automatic translator but rather a set of rules for translating Coq to Agda by hand. Since many basic features can be mapped one-to-one, this process is much more straightforward. However, any use of tactics in the Coq code you'll either have to translate to an explicit proof term in Agda or write your own Agda reflection macros (since there is no full tactic library for Agda yet).
To answer the specific problem you encountered here: Agda did not try to infer the return type of the tUpdate function because you already specified it to be Set yourself. If you want Agda to infer it for you, you can simply replace the return type with an underscore _ (which works fine in this case):
tUpdate : {A : Set} (m : totalMap A) (x : String) (v : A) → _
tUpdate m x v = λ x' → (if (x == x') then v else m x')
How would one formulate a dependently-typed logic in Agda, but not "cheating" by re-using the Agda type system itself?
I can quite readily define an independently-typed logic:
infixr 5 _⇒_
data Type : Set where
_⇒_ : Type → Type → Type
infix 4 _⊢_
data _⊢_ : List Type → Type → Set where
var : {a : Type} → [ a ] ⊢ a
λ' : {a b : Type} {γ : _} → a ∷ γ ⊢ b → γ ⊢ a ⇒ b
ply : {a b : Type} {γ δ : _} → γ ⊢ a ⇒ b → δ ⊢ a → γ ++ δ ⊢ b
weak : {a b : Type} {γ : _} → γ ⊢ b → a ∷ γ ⊢ b
cntr : {a b : Type} {γ : _} → a ∷ a ∷ γ ⊢ b → a ∷ γ ⊢ b
xchg : {a : Type} {γ δ : _} → γ ↭ δ → γ ⊢ a → δ ⊢ a
I can also roughly follow the LambdaPi tutorial implementation of dependently-typed λ-calculus in Haskell. But it's implictly-typed, unlike my Agda code, and i'm not sure where to even begin to modify my code, as the path which came to mind so far led to infinite regress:
data _⊢_ : List (? ⊢ ?) → (? ⊢ ?) → Set where ...
Google searches for "embedding dependent types in Agda" and the like merely return hits for dependently-typed programming in Agda...
We have done this in our paper on Type Theory in Type Theory which is actually formalised in Agda. The basic idea is that you define Contexts, Types, Terms and Substitutions as a mutual inductive definition. We only define typed objects so we never have to define untyped things or a typing judgement. Typing is defined via dependency so for example types depend on contexts and terms on types and contexts. To formulate definitional equality we use ideas from Homotopy Type Theory and allow equality constructors. This meant that we had to axiomatise instances of higher inductive types or to be precise quotient inductive inductive types. This should be soon possible out of the box in cubical Agda.
http://www.cs.nott.ac.uk/~psztxa/publ/tt-in-tt.pdf
#article{altenkirch2016type,
title={Type theory in type theory using quotient inductive types},
author={Altenkirch, Thorsten and Kaposi, Ambrus},
journal={ACM SIGPLAN Notices},
volume={51},
number={1},
pages={18--29},
year={2016},
publisher={ACM}
}
In Haskell i can define an endofunctor fixpoint so:
data Fix f = Fix (f (Fix f))
But in Agda can't:
data Fix (F : Id (Set → Set)) : Set where
fix : (unId F) (Fix F) → Fix F
as it says "Fix is not strictly positive, because it occurs in an argument to a bound variable in the type of the constructor fix in the definition of Fix."
I tried using Coinduction.∞ from the stdlib, in vain:
data Fix (F : Set → Set) : Set where
fix : ∞ (F (Fix F)) → Fix F
or
data Fix (F : Set → Set) : Set where
fix : F (∞ (Fix F)) → Fix F
neither works.
I found this doc which defines polynomial functors Functor and a function [_] : Functor → Set → Set which works:
data Functor : Set₁ where
Id : Functor
Const : Set → Functor
_⊕_ : Functor → Functor → Functor
_⊗_ : Functor → Functor → Functor
[_] : Functor → Set → Set
[ Id ] B = B
[ Const C ] _ = C
[ F ⊕ G ] B = [ F ] B ⊎ [ G ] B
[ F ⊗ G ] B = [ F ] B × [ G ] B
data Fix (F : Functor) : Set where
fix : [ F ] (Fix F) → Fix F
but i'm not sure why that would and this wouldn't, as both have Fix as an argument to the bound variable F.
Can one define a general endofunctor fixpoint in Agda, and if so, how?
EDIT: This was marked as a possible duplicate of 14699334, but the only answer there links to an (the?) Agda tutorial which includes fixpoints of a specific polynomial functor type; i want to know whether one can define this more generally. In particular, i want to define fixpoints of types which may be structurally equal but are nominally inequal.
I've heard the claim that Agda's Martin-Lof Type Theory with Excluded Middle is consistent. How would I go about adding it as a postulate? Also, after Adding LEM, is it then classical first-order logic? By this I mean, do I also have the not (for all) = there exist (not) equivalence? I don't know type theory, so please add additional explanation if you quote any results in type theory.
In MLTT, exists corresponds to a dependent pair which is defined in Data.Product in the standard library. It packages together the existence witness and the proof that it has the right property.
It is not necessary to postulate anything to prove that the negation of an existential statement implies the universal statement of the negated property:
∄⇒∀ : {A : Set} {B : A → Set} →
¬ (∃ λ a → B a) →
∀ a → ¬ (B a)
∄⇒∀ ¬∃ a b = ¬∃ (a , b)
To prove the converse however you do need the law of excluded middle to have a witness appear out of thin air. It is really easy to extend Agda with new postulates, you can simply write (Dec is defined in Relation.Nullary):
postulate LEM : (A : Set) → Dec A
It's always a good thing to remember how to prove double-negation elimination starting from LEM and we will need later on anyway so there it is (case_of_ is defined in Function and explained in README.Case):
¬¬A⇒A : {A : Set} → ¬ (¬ A) → A
¬¬A⇒A {A} ¬¬p =
case LEM A of λ
{ (yes p) → p
; (no ¬p) → ⊥-elim $ ¬¬p ¬p
}
And you can then prove that the negation of a universal statement implies an
existential one like so:
¬∀⇒∃ : {A : Set} {B : A → Set} →
¬ (∀ a → B a) →
∃ λ a → ¬ (B a)
¬∀⇒∃ {A} {B} ¬∀ =
case LEM (∃ λ a → ¬ B a) of λ
{ (yes p) → p
; (no ¬p) → ⊥-elim $ ¬∀ (¬¬A⇒A ∘ ∄⇒∀ ¬p)
}
A gist with all the right imports
I am having problems with rewriting using the setoid_rewrite tactic. In the following instance declaration, I expect that setoid_rewrite fmapComp would rewrite fmap iso ∘ fmap inv to fmap (iso ∘ inv). However, Coq reports that "no progress was made" during rewriting:
Instance functorsPreserveIsomorphisms
`{C : Cat o η} `{D : Cat u ρ}
{a b : o} {φ : o → u} (F : Functor C D φ) (I : a ≅ b) : φ a ≅ φ b.
Proof.
apply (Build_Isomorphism _ _ _ (φ a) (φ b) (fmap iso) (fmap inv)).
o : Type
η : o → o → Type
C : Cat o η
u : Type
ρ : u → u → Type
D : Cat u ρ
a : o
b : o
φ : o → u
F : Functor C D φ
I : a ≅ b
============================
fmap iso ∘ fmap inv ≡ id (φ a)
I don't understand why setoid_rewrite fails. For reference, the same command works in other contexts using the same terms. For example, it rewrites either side of the following goal to the other:
Lemma worksotherwise
`{C : Cat o η} `{D : Cat u ρ}
{a b : o} {φ : o → u} (F : Functor C D φ) (I : a ≅ b) :
fmap iso ∘ fmap inv ≡ fmap (iso ∘ inv)
o : Type
η : o → o → Type
C : Cat o η
u : Type
ρ : u → u → Type
D : Cat u ρ
a : o
b : o
φ : o → u
F : Functor C D φ
I : a ≅ b
============================
fmap iso ∘ fmap inv ≡ fmap (iso ∘ inv)
It's unclear why setoid_rewrite works in the second case but not the first. For reference, ≡ is equiv and fmap is Proper. Other than that ≅, Functor and Cat are classes, I don't see any other relevant facts. Also, setoid_replace works fine.
This is a shot in the dark without seeing the whole development, but sometimes, when you can't see a difference, it means that there's a difference in a part you don't see. Namely, implicit arguments.
For example, you might have an implicit argument somewhere that appears identically in two locations in the working proof attempt, and that appears in two distinct but interconvertible (or even merely equal) in the non-working proof attempt. Occasionally tactics require identical terms to fire up, whereas interconvertible terms would suffice with the same proof tree, and equal terms would suffice with judicious introduction of eq_refl. When you're working with high-level tactics such as the setoid tactics, it can be difficult to understand what's going on under the hood.
Try comparing the situations under Set Printing Implicit or Set Printing All, or working with No Strict Implicit or No Implicit Arguments for a small part of the proof.