Confusion about Morte (calculus of constructions) typing - lambda-calculus

In Morte (an implementation of calculus of constructions) this expression is well typed:
$ morte
( λ(Nat : *)
-> λ(Zero : Nat)
-> Zero
)
(∀(a : *) -> (a -> a) -> a -> a)
(λ(a : *) -> λ(Succ : a -> a) -> λ(Zero : a) -> Zero)
^D
∀(a : *) → (a → a) → a → a
λ(a : *) → λ(Succ : a → a) → λ(Zero : a) → Zero
But this apparently equivalent expression is not:
$ morte
( λ(Nat : *)
-> ( λ(Zero : Nat)
-> Zero)
(λ(a : *) -> λ(Succ : a -> a) -> λ(Zero : a) -> Zero)
)
(∀(a : *) -> (a -> a) -> a -> a)
^D
morte:
Context:
Nat : *
Expression: (λ(Zero : Nat) → Zero) (λ(a : *) → λ(Succ : a → a) → λ(Zero : a) → Zero)
Error: Function applied to argument of the wrong type
Expected type: Nat
Argument type: ∀(a : *) → ∀(Succ : a → a) → ∀(Zero : a) → a
Why is this?

You simply misplaced a parentheses. Swap the 4th line and the 5 the line, and type check passes.

Related

How to define the range function on a relation in Agda (set theory)

I'm trying to find a way to prove a couple of set theory-based problems in Agda, but I'm having a hard time defining the function range.
I took the definition of Subset from Proving decidability of subset in Agda and built on top of it. This is what I got so far:
open import Data.Bool as Bool using (Bool; true; false; T; _∨_; _∧_)
open import Data.Unit using (⊤; tt)
open import Level using (Level; _⊔_; 0ℓ) renaming (suc to lsuc)
open import Data.Product using (_×_) renaming (_,_ to ⟨_,_⟩)
Subset : ∀ {α} (A : Set α) -> Set _
Subset A = A → Bool
_∈_ : ∀ {α} {A : Set α} → A → Subset A → Set
a ∈ p = T (p a)
Relation : ∀ {α β} (A : Set α) (B : Set β) → Set (α ⊔ β)
Relation A B = Subset (A × B)
Range : ∀ {A B : Set} → Relation A B → Subset B
Range = ?
_⊆_ : ∀ {A : Set} → Subset A → Subset A → Set
A ⊆ B = ∀ x → x ∈ A → x ∈ B
wholeSet : ∀ (A : Set) → Subset A
wholeSet _ = λ _ → true
∀subset⊆set : ∀ {A : Set} {sub : Subset A} → sub ⊆ wholeSet A
∀subset⊆set = λ _ _ → tt
_∩_ : ∀ {A : Set} → Subset A → Subset A → Subset A
A ∩ B = λ x → (A x) ∧ (B x)
⊆-range-∩ : ∀ {A B : Set}
(F G : Relation A B)
→ Range (F ∩ G) ⊆ (Range F ∩ Range G)
⊆-range-∩ f g = ?
The problem is that Range takes as an input a function of type A × B → Bool and must return a function B → Bool such that a value B is true iff there exists a value A × B which is true in the initial function. Basically, I would need to iterate through all values of A to know whether B is in the range of the relation. Something impossible to do, isn't it?
There must be surely a better way to implement Range, doesn't it?
Here is the implementation I suggest :
open import Data.Unit
open import Data.Product renaming (_,_ to ⟨_,_⟩)
open import Data.Sum
open import Function
Change the definition of Subset to go to Set instead of Bool. I know this might be controversial, but in my experience this has always been the way to go, and also this is how subsets are implemented in the standard library. (By the way, if you are interested to see the implementation in the standard library, it is in the file Relation/Unary.agda). I also removed the levels of universe since you didn't use them in your later definitions, which led me to clean up the types of the module.
Subset : Set → Set₁
Subset A = A → Set
The definition of membership is changed accordingly.
_∈_ : ∀ {A} → A → Subset A → Set
a ∈ P = P a
Relation : ∀ A B → Set₁
Relation A B = Subset (A × B)
The range becomes then very natural : b is in the range of R if their exists an a such as R of a and b holds.
Range : ∀ {A B} → Relation A B → Subset B
Range R b = ∃ (R ∘ ⟨_, b ⟩) -- equivalent to ∃ \a → R ⟨ a , b ⟩
_⊆_ : ∀ {A} → Subset A → Subset A → Set
A ⊆ B = ∀ x → x ∈ A → x ∈ B
Not much to say about the wholeset
wholeSet : ∀ A → Subset A
wholeSet _ _ = ⊤
∀subset⊆set : ∀ {A sub} → sub ⊆ wholeSet A
∀subset⊆set _ _ = tt
_∩_ : ∀ {A} → Subset A → Subset A → Subset A
(A ∩ B) x = x ∈ A × x ∈ B
The proof of range inclusion is done very naturally with this definition.
⊆-range-∩ : ∀ {A B} {F G : Relation A B} → Range (F ∩ G) ⊆ (Range F ∩ Range G)
⊆-range-∩ _ ⟨ a , ⟨ Fab , Gab ⟩ ⟩ = ⟨ ⟨ a , Fab ⟩ , ⟨ a , Gab ⟩ ⟩
I also took the liberty to add the corresponding property about union.
_⋃_ : ∀ {A} → Subset A → Subset A → Subset A
(A ⋃ B) x = x ∈ A ⊎ x ∈ B
⋃-range-⊆ : ∀ {A B} {F G : Relation A B} → (Range F ⋃ Range G) ⊆ Range (F ⋃ G)
⋃-range-⊆ _ (inj₁ ⟨ a , Fab ⟩) = ⟨ a , inj₁ Fab ⟩
⋃-range-⊆ _ (inj₂ ⟨ a , Gab ⟩) = ⟨ a , inj₂ Gab ⟩

How to prove `theorem : ¬ ⊤ ≡ ⊥` in Agda?

Following The Haskell Road to Logic, Maths and Programming, one can find p.48 Theorem 2.12.1 ¬ ⊤ ≡ ⊥ and its converse ¬ ⊥ ≡ ⊤
The book uses Haskell and assumes
⊥ = False
⊤ = True
which would yield the Agda type theorem : (p q : Bool) → not p ≡ q which is trivial to prove via refl.
However, can one prove the original theorem without assuming 1 and 2?
trying
-- from software foundations (https://plfa.github.io/Negation/)
postulate
excluded-middle : ∀ {A : Set} → A ⊎ ¬ A
theorem : ¬ ⊤ ≡ ⊥
theorem x = {!!}
of course yields no solution, since we can't construct ⊥, so I guess a proof by contradiction is needed? Also, am I correct that this assumes the law of the excluded middle, which is therefore required as an additional postulate?
Agda says:
I'm not sure if there should be a case for the constructor refl,
because I get stuck when trying to solve the following unification
problems (inferred index ≟ expected index):
⊤ ≟ ⊥
when checking that the expression ? has type ⊥
Thanks!
This is provable in plain Agda without postulates. The solution is that ⊤ ≡ ⊥ allows us to turn any proof of ⊤ into a proof of ⊥.
open import Data.Unit
open import Data.Empty
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
theorem : ¬ (⊤ ≡ ⊥)
theorem eq = subst (λ A → A) eq tt
If ¬ ⊤ ≡ ⊥ is ¬ (⊤ ≡ ⊥), then #Andras Kovacs answer suits for both ¬ ⊤ ≡ ⊥ and ¬ ⊥ ≡ ⊤. If ¬ ⊤ ≡ ⊥ is (¬ ⊤) ≡ ⊥, then the proof requires an equality of types. Usually you should be fine with the proof of existence of isomorphism between ¬ ⊤ and ⊥.
The proof for (¬ ⊤) ≡ ⊥ establishes that ¬ ⊤ is not inhabited.
The proof for (¬ ⊥) ≡ ⊤ then essentially establishes the fact that ¬ ⊥ has only one function, id (hence is isomorphic to all types containing a single element).
All of the following can be constructed using some standard Agda functions, but here the self-sufficient bunch of definitions needed to prove the existence of such isomorphisms. Note False and True are types, not boolean values. Also, extensionality axiom is needed to be able to prove the second theorem, because ¬ ⊥ is a function.
data False : Set where
data True : Set where
tt : True
data _==_ {A : Set} (x : A) : A -> Set where
refl : x == x
false-elim : {A : Set} -> False -> A
false-elim ()
id : {A : Set} -> A -> A
id x = x
const : {A B : Set} -> B -> A -> B
const x _ = x
ap : {A B : Set} -> (A -> B) -> A -> B
ap = id
ap' : {A B : Set} -> A -> (A -> B) -> B
ap' x f = f x
infixl 4 _==_
data Isomorphism {A B : Set} (f : A -> B) (g : B -> A) : Set where
iso : ((x : B) -> f (g x) == id x) ->
((x : A) -> g (f x) == id x) -> Isomorphism f g
Not : Set -> Set
Not A = A -> False
not-True-iso-False : Isomorphism (ap' tt) false-elim
not-True-iso-False = iso (\x -> false-elim {ap' tt (false-elim x) == id x} x)
\not-true -> false-elim (not-true tt)
-- extensionality: if functions produce equal results for all inputs, then the functions are equal
postulate ext : {A B : Set} -> (f g : A -> B) -> ((x : A) -> f x == g x) -> f == g
not-False-iso-True : Isomorphism {Not False} {True} (const tt) (const id)
not-False-iso-True = iso is-true is-not-false where
is-true : (x : True) -> const tt (const {True} (id {Not False})) == id x
is-true tt = refl
is-not-false : (x : Not False) -> const id (const {Not False} tt) == id x
is-not-false x = ext (const id (const {Not False} tt)) x \()
Now, if we define _==_ for any level of type universe, then we can introduce the axiom about type equality: if two types have an isomporphism, then they are equal.
open import Agda.Primitive
data _==_ {a : Level} {A : Set a} (x : A) : A -> Set a where
refl : x == x
postulate iso-is-eq : {A B : Set} {f : A -> B} {g : B -> A} ->
Isomorphism f g -> A == B
not-True-is-False : (Not True) == False
not-True-is-False = iso-is-eq not-True-iso-False
not-False-is-True : (Not False) == True
not-False-is-True = iso-is-eq not-False-iso-True

How to define arbitrary partial order relation and prove its properties?

I have a simple data type with all nullary constructors and wish to define a partial order for it, including a Relation.Binary.IsPartialOrder _≡_.
My use case: the type is the type of sorts in an abstract syntax tree (statement, expression, literal, item), and i want a constructor of the AST which effectively upcasts a term (item ≤ statement, expression ≤ statement, literal ≤ expression).
data Sort : Set where stmt expr item lit : Sort
So far i have this:
data _≤_ : Rel Sort lzero where
refl : {a : Sort} → a ≤ a
trans : {a b c : Sort} → a ≤ b → b ≤ c → a ≤ c
expr≤stmt : expr ≤ stmt
item≤stmt : item ≤ stmt
lit≤expr : lit ≤ expr
I can define isPreorder but have no idea how to define antisym:
open import Agda.Primitive
open import Data.Empty using (⊥)
open import Data.Unit using (⊤)
open import Relation.Binary
open import Relation.Binary.PropositionalEquality using (_≡_)
import Relation.Binary.PropositionalEquality as PropEq
module Core.Sort where
data Sort : Set where
stmt expr item lit : Sort
data _≤_ : Rel Sort lzero where
refl : {a : Sort} → a ≤ a
trans : {a b c : Sort} → a ≤ b → b ≤ c → a ≤ c
lit≤expr : lit ≤ expr
expr≤stmt : expr ≤ stmt
item≤stmt : item ≤ stmt
≤-antisymmetric : Antisymmetric _≡_ _≤_
≤-antisymmetric =
λ { refl _ → PropEq.refl;
_ refl → PropEq.refl;
(trans refl x≤y) y≤x → ≤-antisymmetric x≤y y≤x;
(trans x≤y refl) y≤x → ≤-antisymmetric x≤y y≤x;
x≤y (trans refl y≤x) → ≤-antisymmetric x≤y y≤x;
x≤y (trans y≤x refl) → ≤-antisymmetric x≤y y≤x;
x≤z (trans z≤y (trans y≤w w≤x)) → _ }
I'm not sure what to do in the last clause (and all further clauses like it), and in any case this is cumbersome.
Am i missing a more convenient method to define an arbitrary partial order?
Notice that, for any given x and y, whenever x ≤ y is provable, there are infinitely many such proofs. E.g., stmt ≤ stmt is proved by refl and by trans refl refl and so forth. This may (but probably doesn't) explain why it's troublesome (and maybe impossible) to prove ≤-antisymmetric.
In any case, the following definition of "less than or equal", _≼_, has the property that whenever x ≼ y is provable, there is exactly one proof of it. Bonus: I can prove antisym for it.
-- x ≺ y = x is contiguous to and less than y
data _≺_ : Rel Sort lzero where
lit≺expr : lit ≺ expr
expr≺stmt : expr ≺ stmt
item≺stmt : item ≺ stmt
-- x ≼ y = x is less than or equal to y
data _≼_ : Rel Sort lzero where
refl : {a : Sort} → a ≼ a
trans : {a b c : Sort} → a ≺ b → b ≼ c → a ≼ c
≼-antisymmetric : Antisymmetric _≡_ _≼_
≼-antisymmetric refl _ = PropEq.refl
≼-antisymmetric _ refl = PropEq.refl
≼-antisymmetric (trans lit≺expr _) (trans lit≺expr _) = PropEq.refl
≼-antisymmetric (trans lit≺expr refl) (trans expr≺stmt (trans () _))
≼-antisymmetric (trans lit≺expr (trans expr≺stmt _)) (trans expr≺stmt (trans () _))
≼-antisymmetric (trans lit≺expr (trans expr≺stmt _)) (trans item≺stmt (trans () _))
≼-antisymmetric (trans expr≺stmt _) (trans expr≺stmt _) = PropEq.refl
≼-antisymmetric (trans expr≺stmt (trans () _)) (trans lit≺expr _)
≼-antisymmetric (trans expr≺stmt (trans () _)) (trans item≺stmt _)
≼-antisymmetric (trans item≺stmt (trans () _)) (trans lit≺expr _)
≼-antisymmetric (trans item≺stmt (trans () _)) (trans _ _)

Haskell Error: Non type-variable argument in the constraint: Num (a -> a -> a -> a)

I'm new to Haskell and am trying to run the following example code from my book:
entire file:
-- my name
splitAt1 :: [a] -> ([a], [a])
splitAt1 xs = (take 2 xs, drop 2 xs)
I'm testing by running the line:
splitAt1 [1 2 3 4]
The idea is that the input array is split into two arrays at the index 2. However, I am getting the following error:
Non type-variable argument
in the constraint: Num (a -> a -> a -> a)
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall a a1 a2 a3.
(Num a1, Num a2, Num a3, Num (a1 -> a2 -> a3 -> a)) =>
([a], [a])
Could anyone help me decode the error message and perhaps what is wrong with the code?
The function is fine, it's your argument that's off.
Try splitAt1 [1,2,3,4] instead of splitAt1 [1 2 3 4] and it should work.

Why can't I remove the Ord Typeclass from this haskell implementation of Kadane's algorithm?

I have been implementing kadane's algorithm in haskell, AFAIK it is working correctly
kadane' :: (Ord a, Num a) => [a] -> a
kadane' xs = head$ foldl maxsub [0,0] xs
maxsub :: (Ord a, Num a) => [a] -> a -> [a]
maxsub x y
| last(x)+y > head(x) = if last(x)+y > 0 then [last(x)+y, last(x)+y] else [last(x)+y, 0]
| otherwise = if last(x)+y > 0 then [head(x), last(x)+y] else [head(x), 0]
I want to remove Ord typeclass from function's type specification, since I can't find maximum sub array for all the types that can be ordered. But I can't get rid of the Ord typeclass from the type specification. I wrote them initially by asking haskell's type inference as shown below
*Main> :t kadane'
kadane' :: (Ord a, Num a) => [a] -> a
*Main> :t maxsub
maxsub :: (Ord a, Num a) => [a] -> a -> [a]
*Main>
If I remove Ord Typeclass as shown below
kadane' :: (Num a) => [a] -> a
kadane' xs = head$ foldl maxsub [0,0] xs
maxsub :: (Num a) => [a] -> a -> [a]
maxsub x y
| last(x)+y > head(x) = if last(x)+y > 0 then [last(x)+y, last(x)+y] else [last(x)+y, 0]
| otherwise = if last(x)+y > 0 then [head(x), last(x)+y] else [head(x), 0]
and compiling the above code throws the following error
*Main> :l kadanes.hs
[1 of 1] Compiling Main ( kadanes.hs, interpreted )
kadanes.hs:6:21:
Could not deduce (Ord a) arising from a use of ‘>’
from the context (Num a)
bound by the type signature for maxsub :: Num a => [a] -> a -> [a]
at kadanes.hs:4:11-36
Possible fix:
add (Ord a) to the context of
the type signature for maxsub :: Num a => [a] -> a -> [a]
In the expression: last (x) + y > head (x)
In a stmt of a pattern guard for
an equation for ‘maxsub’:
last (x) + y > head (x)
In an equation for ‘maxsub’:
maxsub x y
| last (x) + y > head (x)
= if last (x) + y > 0 then
[last (x) + y, last (x) + y]
else
[last (x) + y, 0]
| otherwise
= if last (x) + y > 0 then
[head (x), last (x) + y]
else
[head (x), 0]
Failed, modules loaded: none.
Prelude>
According to the Possible Fix reported in the error I need to add Ord typeclass again, What am I doing wrong ?
And also please evaluate the correctness of the algorithm, if possible suggest alternative ways
You cannot remove Ord since you are using functions like < and > and operating them on polymorphic type. See their type:
λ> :t (<)
(<) :: Ord a => a -> a -> Bool
But if you instead limit your polymorphic code to operate only on Int or any other monomorphic instance for which Ord instance is already defined, then you can remove it:
maxsub :: [Int] -> Int -> [Int]
maxsub x y
| last(x)+y > head(x) = if last(x)+y > 0 then [last(x)+y, last(x)+y] else [last(x)+y, 0]
| otherwise = if last(x)+y > 0 then [head(x), last(x)+y] else [head(x), 0]
kadane' :: [Int] -> Int
kadane' xs = head$ foldl maxsub [0,0] xs

Resources