I'm new to agda, and following a simple example in the book little MLer. Could anyone help me to figure out why the compiler gives me a parsing error?
Thank you
data Shish (a : Set) : Set where
Bottom : a → Shish a
Onion : Shish a → Shish a
Lamb : Shish a → Shish a
Tomato : Shish a → Shish a
data Rod : Set where
Dagger : Rod
Fork : Rod
Sword : Rod
data Plate : Set where
Gold-plate : Plate
Silver-plate : Plate
Brass-plate : Plate
what_bottom : Shish (a : Set) → Bool
what_bottom (Bottom x) → x
what_bottom (Onion x) → what_bottom x
what_bottom (Lamb x) → what_bottom x
what_bottom (Tomato x) → what_bottom x
/Volumes/Little/mko_io/cat/tmp/mler.agda:54,24-24
/Volumes/Little/mko_io/cat/tmp/mler.agda:54,24: Parse error
:<ERROR>
Set) → Bool
what_bottom (Bott...
The data type definitions are properly defined, but this is not the way one defines functions in Agda. A good starting tutorial is Dependent types at work
Functions are defined with the equal sign.
id : {A : Set} → A → A
id a = a
Moreover, the dependent type must be declared before like so either implicitly or explicitly.
what_bottom : {A : Set} → Shish A → ...
Lastly, that function cannot be defined with a return type Bool. It can have type a though.
As an additional syntactic point, in Agda, underscores are placeholders for mixfix arguments: what_bottom is a mixfix name with one parameter between what and bottom. So you'll end up with a function that you'd use as what (Onion $ Lamb $ Bottom) bottom which is probably not what you intended. Just call it whatBottom or what‿bottom if you're feeling extra.
Related
As I described in the title, the supposed code should be like this:
data Mode : Set where
⇛ : Mode
⇚ : Mode
infix 4 _⊢_
data _⊢_ : Context → Term → Mode → Type → Set where
⊢-int : ∀ {Γ n}
→ Γ ⊢ (lit n) ⇛ Int
And it gave me the error
Mode → Type → Set should be a sort, but it isn't
when checking that the inferred type of an application
Mode → Type → Set
matches the expected type
_30
I sort of know what the type is. To deal with it, I may need to put some non-meaningful symbols between, e.g.
data _⊢_._._ where
which is not good-looking and I'm tired of writing those. Just want to know any solutions for this situation?
You can hardcode the mode right into the data type declaration and create two separate data types:
data _⊢_⇛_ : Context → Term → Type → Set where
⊢-int : ∀ {Γ n}
→ Γ ⊢ lit n ⇛ Int
data _⊢_⇚_ : Context → Term → Type → Set where
Note that Agda is able to recognize that ⇛ in _⊢_⇛_ is different to the one from Mode, so there's no ambiguity (unless you also add _⊢_, at which point things become ambiguous).
Alternatively, you can make it
data Mode : Set where
_⇛_ : Term → Type → Mode
_⇚_ : Term → Type → Mode
infix 4 _⊢_
infix 5 _⇛_ _⇚_
data _⊢_ : Context → Mode → Set where
⊢-int : ∀ {Γ n}
→ Γ ⊢ lit n ⇛ Int
During some development using cubical-agda, I noticed (and later checked) that my current goal, if proven would also imply such theorem:
parametric? : ∀ ℓ → Type (ℓ-suc ℓ)
parametric? ℓ = (f : {A : Type ℓ} → List A ≃ List A)
→ (A : Type ℓ) → length ∘ equivFun (f {A}) ≡ length
I suspect that this is example of parametric theorem, which is true, but is unprovable in cubical agda. Is it the case?
Can I safely assume that my current goal is also unprovable?
Yes, because it's false in the standard (simplicial sets) model.
If excluded middle holds, we can define f : {A : Type ℓ} → List A ≃ List A by first doing a case analysis on whether A is contractible or not. If A is not contractible, f gives the identity equivalence, but if A is contractible, then List A is equivalent to Nat, and, f can give an equivalence that, e.g., permutes odds and evens.
In the following data type,
data _≡_ {A : Set} (x : A) : A → Set where
refl : x ≡ x
I am trying to understand this like:
If A is of type Set and is implicit and x is the first argument and of type A, then this will construct a data of type A → Set.
Please explain it. I did not get from where it getting second x, in constructor refl.
The crucial distinction here is between parameters (A and x in this case) and indices (the A in A → Set).
The parameters are located on the left hand side of the colon in the data declaration. They are in scope in the body of the type and may not vary (hence their name). This is what allows you to write data declarations such as List where the type of the elements contained in the List is stated once and for all:
data List (A : Set) : Set where
nil : List A
cons : A → List A → List A
rather than having to mention it in every single constructor with a ∀ A →:
data List : Set → Set1 where
nil : ∀ A → List A
cons : ∀ A → A → List A → List A
The indices are located on the right hand side of the colon in the data declaration. They can be either fresh variables introduced by a constructor or constrained to be equal to other terms.
If you work with natural numbers you can, for instance, build a predicate stating that a number is not zero like so:
open import Data.Nat
data NotZero : (n : ℕ) → Set where
indeed1 : NotZero (suc zero)
indeed2+ : ∀ p → NotZero (suc (suc p))
Here the n mentioned in the type signature of the data declaration is an index. It is constrained differently by different constructors: indeed1 says that n is 1 whilst indeed2+ says that n has the shape suc (suc p).
Coming back to the declaration you quote in your question, we can reformulate it in a fully-explicit equivalent form:
data Eq (A : Set) (x : A) : (y : A) → Set where
refl : Eq A x x
Here we see that Eq has two parameters (A is a set and x is an element of A) and an index y which is the thing we are going to claim to be equal to x. refl states that the only way to build a proof that two things x and y are equal is if they are exactly the same; it constraints y to be exactly x.
I'm easily able to obtain a list of Keys, as follows:
open import Relation.Binary
open import Relation.Binary.PropositionalEquality using (_≡_)
module AVL-Tree-Functions
{ k v ℓ } { Key : Set k }
( Value : Key → Set v )
{ _<_ : Rel Key ℓ }
( isStrictTotalOrder : IsStrictTotalOrder _≡_ _<_ )
where
open import Data.AVL Value isStrictTotalOrder public
open import Data.List.Base
open import Function
open import Data.Product
keys : Tree → List Key
keys = Data.List.Base.map proj₁ ∘ toList
But I'm not clear on how to specify the type of function that returns a list of values. Here's my first attempt:
-- this fails to typecheck
values : Tree → List Value
values = Data.List.Base.map proj₂ ∘ toList
Relatedly, I'm also confused about the declaration of Value in Data.AVL. With ( Value : Key → Set v ), it looks like the type of each Value in the tree is dependent on the key? Or, something like that. I then figured that proj₂ would be returning something of type Set v, so I tried this:
-- this also fails to typecheck
values : Tree → List (Set v)
values = Data.List.Base.map proj₂ ∘ toList
But that doesn't work either (it fails with a different error). Please show how to get a list of values from a Data.AVL.Tree (or explain why it's impossible). Bonus: explain why my two attempts failed.
P.s. This is using version 2.4.2.3 of Agda and the agda-stdlib.
it looks like the type of each Value in the tree is dependent on the
key?
Yes. And that's why your code doesn't typecheck — Lists are homogeneous, but different Values have different indices (i.e. depend on different Keys) and hence different types.
You can use heterogeneous lists as in gallais' answer, but indexed lists might be enough in your case:
open import Level
data IList {ι α} {I : Set ι} (A : I -> Set α) : Set (ι ⊔ α) where
[]ᵢ : IList A
_∷ᵢ_ : ∀ {i} -> A i -> IList A -> IList A
projs₂ : ∀ {α β} {A : Set α} {B : A -> Set β} -> List (Σ A B) -> IList B
projs₂ [] = []ᵢ
projs₂ ((x , y) ∷ ps) = y ∷ᵢ projs₂ ps
Or you can combine the techniques:
data IHList {ι α} {I : Set ι} (A : I -> Set α) : List I -> Set (ι ⊔ α) where
[]ᵢ : IHList A []
_∷ᵢ_ : ∀ {i is} -> A i -> IHList A is -> IHList A (i ∷ is)
projs₂ : ∀ {α β} {A : Set α} {B : A -> Set β}
-> (xs : List (Σ A B)) -> IHList B (Data.List.Base.map proj₁ xs)
projs₂ [] = []ᵢ
projs₂ ((x , y) ∷ ps) = y ∷ᵢ projs₂ ps
What Value : Key → Set v means is that the type of the value may depend on the key it is associated to. This means that an AVL tree may contain Booleans, Nats, and so on as long as the key they are stored in reflects that fact. A bit like the fact that records can store values of different types (the types are determined by the field's name).
Now, they are different ways to do this: you can extract the content of the whole tree to a list of key / value pairs (because a list's elements are all the same, you need to build a pair here so that everything has the same type Σ Key Value). This is what toList does.
An alternative is to use what is usually called an HList (the H stands for heterogeneous) which stores in a list at the type level the type each one of its elements is supposed to have. I define it here by induction on the set of elements for size reasons but it is not at all crucial (if you were to define it as a datatype, it would live one level higher):
open import Level
open import Data.Unit
HList : {ℓ : Level} (XS : List (Set ℓ)) → Set ℓ
HList [] = Lift ⊤
HList (X ∷ XS) = X × HList XS
Now, you can give the type of the HList of values. Given t a Tree, it uses your keys to extract the list of keys and turns them into Sets by mapping Value over the list.
values : (t : Tree) → HList (List.map Value (keys t))
Extracting the values can then be done with the help of an auxiliary function working along the list produced by toList:
values t = go (toList t) where
go : (kvs : List (Σ Key Value)) → HList (List.map Value $ List.map proj₁ kvs)
go [] = lift tt
go (kv ∷ kvs) = proj₂ kv , go kvs
Agda gives me a parse error when trying to type check this:
record Monad (M : Set → Set) : Set1 where
field return : {A : Set} → A → M A
_>>=_ : {A B : Set} → M A → (A → M B) → M B
What I am doing wrong?
EDIT: I've tried flipping the order of the fields while commenting out the bottom one and it type checks => I'm not using correct record,field syntax i guess
EDIT2:
record Monad (M : Set → Set) : Set1 where
field
bind : {A B : Set} → M A → (A → M B) → M B
return : {A : Set} → A → M A
Okay I fiddled around some more and it started working. Formatted like above. Putting this in an edit since I still don't know what caused my original snippet to not work.