I would like to test some definitions in system F using Agda as my typechecker and evaluator.
My first attempt to introduce Church natural numbers was by writing
Num = forall {x} -> (x -> x) -> (x -> x)
Which would be used just like a regular type alias:
zero : Num
zero f x = x
However the definition of Num does not type(kind?)check. What is the most proper way to make it working and be as close as possible to the system F notation?
The following would typecheck
Num : Set₁
Num = forall {x : Set} -> (x -> x) -> (x -> x)
zero : Num
zero f x = x
but as you see Num : Set₁, this might become a problem and you'll need --type-in-type
Related
I was looking at the definition of cong:
cong : ∀ {a b} {A : Set a} {B : Set b} (f : A → B) {x y} → x ≡ y → f x ≡ f y
cong f refl = refl
And I couldn't understand why it is well-typed. In particular, it seems like the implicit argument of refl must be both f x and f y. To make things more clear, I wrote a non-implicit version of equality, and attempted to replicate the proof:
data Eq : (A : Set) -> A -> A -> Set where
refl : (A : Set) -> (x : A) -> Eq A x x
cong : (A : Set) -> (B : Set) -> (f : A -> B) ->
(x : A) -> (y : A) -> (e : Eq A x y) -> Eq B (f x) (f y)
cong A B f x y e = refl B (f x)
This results in a type error:
x != y of type A when checking that the expression refl B (f x) has type Eq B (f x) (f y)
As one would expect. What could I possibly have instead of (f x)? Am I missing something?
Dependent pattern matching at your service.
If we make a hole in your cong
cong : (A : Set) -> (B : Set) -> (f : A -> B) ->
(x : A) -> (y : A) -> (e : Eq A x y) -> Eq B (f x) (f y)
cong A B f x y e = {!refl B (f x)!}
and look into it, we'll see
Goal: Eq B (f x) (f y)
Have: Eq B (f x) (f x)
so the values are indeed different. But once you pattern match on e:
cong : (A : Set) -> (B : Set) -> (f : A -> B) ->
(x : A) -> (y : A) -> (e : Eq A x y) -> Eq B (f x) (f y)
cong A B f x y (refl .A .x) = {!refl B (f x)!}
the fact that x is the same thing as y is revealed and the context is silently rewritten: each occurrence of y is replaced by x, so looking into the hole we now see
Goal: Eq B (f x) (f x)
Have: Eq B (f x) (f x)
Note that we can write
cong A B f x .x (refl .A .x) = refl B (f x)
i.e. do not bind y at all and just say that it's the same as x via a dot-pattern. We gained this information by pattern matching on e : Eq A x y, because once the match is performed we know that it's e : Eq A x x actually, because that's what the type signature of refl says. Unification of Eq A x y and Eq A x x results in a trivial conclusion: y equals x and the whole context is adjusted accordingly.
That's the same logic as with Haskell GADTs:
data Value a where
ValueInt :: Int -> Value Int
ValueBool :: Bool -> Value Bool
eval :: Value a -> a
eval (ValueInt i) = i
eval (ValueBool b) = b
when you match on ValueInt and get i of type Int, you also reveal that a equals Int and add this knowledge to the context (via an equality constraint) which makes a and Int unifiable later. That is how we're able to return i as a result: because a from the type signature and Int unify perfectly as we know from the context.
The following Agda function should lookup a list, looping back on index overflows:
module Test where
open import Prelude.Nat
open import Prelude.List
roundIndex : {A : Set} -> Nat -> A -> List A -> A
roundIndex n x xs = go n xs where
go : {A : Set} -> Nat -> List A -> A
go (suc n) (x ∷ xs) = go n xs
go (suc n) [] = go n xs
go zero (x ∷ xs) = x
go zero [] = x
But won't compile with the following cryptic error:
/Users/v/vic/dev/agda/Test.agda:10,25-32
.A !=< .A₁ of type Set
when checking that the expression go n xs has type .A₁
It seems like Agda isn't properly passing the implicit A to go, but passing it explicitly didn't solve the problem. What is this error? Also, that is !=<?
The error is that go works for any A, but you try to return outer x and xs with outer A types. The go-bound A and roundIndex-bound A types are different, hence the error. In general, bound type variables are only equal to themselves during conversion checking. It's not Agda-specific, as you could reproduce the same error in Haskell as well.
The solution is to remove the inner type quantification:
roundIndex : {A : Set} -> Nat -> A -> List A -> A
roundIndex {A} n x xs = go n xs where
go : Nat -> List A -> A
go (suc n) (x ∷ xs) = go n xs
go (suc n) [] = go n xs
go zero (x ∷ xs) = x
go zero [] = x
Now there's only one shared A around.
Consider the following self-contained program:
module Test where
record Σ {A : Set} (B : A -> Set) : Set where
constructor _,_
field
fst : A
snd : B fst
open Σ public
infixr 0 _,_
_×_ : Set -> Set -> Set
A × B = Σ (\ (_ : A) -> B)
infixr 10 _×_
f : {A B : Set} → A × B → A
f x = {!!}
If you C-c C-l in the goal, you get:
Goal: .A
————————————————————————————————————————————————————————————
x : Σ (λ _ → .B)
.B : Set
.A : Set
i.e. you see the underlying sigma, and the type of the binder of the lambda is hidden. This is pretty annoying. Is there a way to make Agda show the type of binders that don't bind names by default?
This is Agda 2.3.2.2.
Agda 2.4.3 displays x : .A × .B.
You can use the abstract keyword:
abstract
_×_ : Set -> Set -> Set
A × B = Σ (\ (_ : A) -> B)
fst' : ∀ {A B} -> A × B -> A
fst' (x , y) = x
snd' : ∀ {A B} -> A × B -> B
snd' (x , y) = y
But that's definitely overkill (and it looks like pattern synonyms do not work in abstract blocks).
It's much more annoying to me, that Agda doesn't want to reduce functions like flip and especially _∘_, but unfolds some functions with really long definitions. Agda needs a mechanism for fixing these problems.
It appears that this problem has been fixed in the latest version of Agda, so you should upgrade.
I have a list
data List (X : Set) : Set where
<> : List X
_,_ : X -> List X -> List X
a definition for equality
data _==_ {l}{X : Set l}(x : X) : X -> Set l where
refl : x == x
and congruence
cong : forall {k l}{X : Set k}{Y : Set l}(f : X -> Y){x y} -> x == y -> f x == f y
cong f refl = refl
I am trying to prove
propFlatten2 : {X : Set } ( xs0 : List X ) (x : X) (xs1 : List X) (xs2 : List X)
-> ( xs0 ++ x , xs1 ) ++ xs2 == xs0 ++ (x , xs1 ++ xs2 )
propFlatten2 <> x xs1 xs2 = refl
propFlatten2 (x , xs0) x₁ xs1 xs2 = cong (λ l -> x , l) {!!}
Is there a better way to use directly the constructor _,_ other than through a lambda in the last line ?
Agda doesn't have any special syntax for partial application of operators. You can, however, use the operators in their usual prefix version:
x + y = _+_ x y
This is convenient when you need to partially apply leftmost argument(s):
_+_ 1 = λ x → 1 + x
When you need to partially apply arguments going from the right, your options are more limited. As mentioned in the comments, you could use one of the convenience functions such as flip (found in Function):
flip f x y = f y x -- Type omitted for brevity.
And then simply flip the arguments of _+_:
flip _+_ 1 = λ x → x + 1
Sometimes you find operators whose only purpose is to make the code a bit nicer. Best example I can think of is probably Data.Product.,_. When you write a dependent pair (Data.Product.Σ), sometimes the first part of the pair can be filled in automatically. Instead of writing:
_ , x
You can just write:
, x
It's hard to say when writing a specialized operator such as the one above is actually worth it; if your only use case is using it with congruence, I'd just stick with the lambda since it makes it very clear what's going on.
I am writing a basic monadic parser in Idris, to get used to the syntax and differences from Haskell. I have the basics of that working just fine, but I am stuck on trying to create VerifiedSemigroup and VerifiedMonoid instances for the parser.
Without further ado, here's the parser type, Semigroup, and Monoid instances, and the start of a VerifiedSemigroup instance.
data ParserM a = Parser (String -> List (a, String))
parse : ParserM a -> String -> List (a, String)
parse (Parser p) = p
instance Semigroup (ParserM a) where
p <+> q = Parser (\s => parse p s ++ parse q s)
instance Monoid (ParserM a) where
neutral = Parser (const [])
instance VerifiedSemigroup (ParserM a) where
semigroupOpIsAssociative (Parser p) (Parser q) (Parser r) = ?whatGoesHere
I'm basically stuck after intros, with the following prover state:
-Parser.whatGoesHere> intros
---------- Other goals: ----------
{hole3},{hole2},{hole1},{hole0}
---------- Assumptions: ----------
a : Type
p : String -> List (a, String)
q : String -> List (a, String)
r : String -> List (a, String)
---------- Goal: ----------
{hole4} : Parser (\s => p s ++ q s ++ r s) =
Parser (\s => (p s ++ q s) ++ r s)
-Parser.whatGoesHere>
It looks like I should be able to use rewrite together with appendAssociative somehow,
but I don't know how to "get inside" the lambda \s.
Anyway, I'm stuck on the theorem-proving part of the exercise - and I can't seem to find much Idris-centric theorem proving documentation. I guess maybe I need to start looking at Agda tutorials (though Idris is the dependently-typed language I'm convinced I want to learn!).
The simple answer is that you can't. Reasoning about functions is fairly awkward in intensional type theories. For example, Martin-Löf's type theory is unable to prove:
S x + y = S (x + y)
0 + y = y
x +′ S y = S (x + y)
x +′ 0 = x
_+_ ≡ _+′_ -- ???
(as far as I know, this is an actual theorem and not just "proof by lack of imagination"; however, I couldn't find the source where I read it). This also means that there is no proof for the more general:
ext : ∀ {A : Set} {B : A → Set}
{f g : (x : A) → B x} →
(∀ x → f x ≡ g x) → f ≡ g
This is called function extensionality: if you can prove that the results are equal for all arguments (that is, the functions are equal extensionally), then the functions are equal as well.
This would work perfectly for the problem you have:
<+>-assoc : {A : Set} (p q r : ParserM A) →
(p <+> q) <+> r ≡ p <+> (q <+> r)
<+>-assoc (Parser p) (Parser q) (Parser r) =
cong Parser (ext λ s → ++-assoc (p s) (q s) (r s))
where ++-assoc is your proof of associative property of _++_. I'm not sure how would it look in tactics, but it's going to be fairly similar: apply congruence for Parser and the goal should be:
(\s => p s ++ q s ++ r s) = (\s => (p s ++ q s) ++ r s)
You can then apply extensionality to get assumption s : String and a goal:
p s ++ q s ++ r s = (p s ++ q s) ++ r s
However, as I said before, we don't have function extensionality (note that this is not true for type theories in general: extensional type theories, homotopy type theory and others are able to prove this statement). The easy option is to assume it as an axiom. As with any other axiom, you risk:
Losing consistency (i.e. being able to prove falsehood; though I think function extensionality is OK)
Breaking reduction (what does a function that does case analysis only for refl do when given this axiom?)
I'm not sure how Idris handles axioms, so I won't go into details. Just beware that axioms can mess up some stuff if you are not careful.
The hard option is to work with setoids. A setoid is basically a type equipped with custom equality. The idea is that instead of having a Monoid (or VerifiedSemigroup in your case) that works on the built-in equality (= in Idris, ≡ in Agda), you have a special monoid (or semigroup) with different underlying equality. This is usually done by packing the monoid (semigroup) operations together with the equality and bunch of proofs, namely (in pseudocode):
= : A → A → Set -- equality
_*_ : A → A → A -- associative binary operation
1 : A -- neutral element
=-refl : x = x
=-trans : x = y → y = z → x = z
=-sym : x = y → y = x
*-cong : x = y → u = v → x * u = y * v -- the operation respects
-- our equality
*-assoc : x * (y * z) = (x * y) * z
1-left : 1 * x = x
1-right : x * 1 = x
The choice of equality for parsers is clear: two parsers are equal if their outputs agree for all possible inputs.
-- Parser equality
_≡p_ : {A : Set} (p q : ParserM A) → Set
Parser p ≡p Parser q = ∀ x → p x ≡ q x
This solution comes with different tradeoffs, namely that the new equality cannot fully substitute the built-in one (this tends to show up when you need to rewrite some terms). But it's great if you just want to show that your code does what it's supposed to do (up to some custom equality).