I'm just starting with Agda but know some Haskell and would like to know how to define the Store Comonad in Agda.
This is what I have until now:
open import Category.Comonad
open import Data.Product
Store : Set → Set → ((Set → Set) × Set)
Store s a = ((λ s → a) , s)
StoreComonad : RawComonad (λ s a → (Store s a))
StoreComonad = record
{ extract (Store s a) = extract s a
; extend f (Store s a = Store (extend (λ s' a' → f (Store s' a')) s) a
} where open RawComonad
For now I'm getting the following error:
Parse error
=<ERROR>
extract s a
; extend f (Sto...
I'm not too sure what it is I'm doing wrong. Any help would be appreciated! Thanks!
EDIT
I think I'm getting closer. I replaced the fields in the record using matching lambdas:
Store : Set → Set → ((Set → Set) × Set)
Store s a = ((λ s → a) , s)
StoreComonad : RawComonad (λ s a → (Store s a))
StoreComonad = record
{ extract = λ st → (proj₁ st) (proj₂ st)
; duplicate = λ st → Store (λ s → Store (proj₁ st) s) (proj₂ st)
; extend = λ g st → g (duplicate st)
} where open RawComonad
RawComonad is from https://github.com/agda/agda-stdlib/blob/master/src/Category/Comonad.agda
and has the signature
record RawComonad (W : Set f → Set f) : Set (suc f)
and Store is based on type Store s a = (s -> a, s) in Haskell.
Now the error I'm getting is:
(a : Set) → Σ (Set → Set) (λ x → Set) !=< Set
when checking that the expression λ a → Store s a has type Set
I'm wondering if this error has to do with this line:
StoreComonad : RawComonad (λ s a → (Store s a))
I find that the compilation error messages in Agda don't give many clues or I haven't yet been able to understand them well.
Your problem is that λ s a → (Store s a) (or, eta-contracted, Store) is not a comonad; its type (or, for your Haskell intuition, we could say its kind) is not right.
However, for any choice of s, Store s is! So let's write that:
StoreComonad : ∀ {s : Set} → RawComonad (Store s)
The rest of the definition of StoreComonad will follow easily.
As an aside, you can make the definition of StoreComonad nicer by using pattern-matching lambdas instead of using explicit projections (and please do read that link because it seems you have mixed up normal lambdas with pattern-matching ones); e.g:
extract = λ { (f , a) → f a }
and so on.
Wow, ok, I think silence was the answer I needed. I managed to advance quite a bit on defining the Store Comonad:
S : Set
S = ℕ
Store : Set → Set
Store A = ((S → A) × S)
pos : ∀ {A : Set} → Store A → S
pos = λ st → proj₂ st
peek : ∀ {A : Set} → S → Store A → A
peek = λ s → λ st → (proj₁ st) s
fmap : ∀ {A : Set} {B : Set} → (A → B) → Store A → Store B
fmap = λ f → λ st → ((f ∘ proj₁ st) , proj₂ st)
duplicate' : ∀ {A : Set} → (Store A) → Store (Store A)
duplicate' = λ st → (λ s' → proj₁ st , s') , proj₂ st
StoreComonad : RawComonad Store
StoreComonad = record
{ extract = λ st → (proj₁ st) (proj₂ st)
; extend = λ g st → fmap g (duplicate' st)
} where open RawComonad
along the way I learned that C-c-C-l and C-c-C-r with ? can be quite helpful in trying to find the type that is needed to fill the ?. I used ? for proving some examples before but hadn't tried using it to find how to write a type.
What's left.. I would like to make S not just a Nat.
Related
Say I have type dependent on Nat
data MyType : (i : ℕ) → Set where
cons : (i : ℕ) → MyType i
and a function:
combine : {i₁ i₂ : ℕ} → MyType i₁ → MyType i₂ → MyType (i₁ ⊔ i₂)
Now I'm trying to write a function:
create-combined : (i : ℕ) → MyType i
create-combined i = combine {i} {i} (cons i) (cons i)
Unfortunately, I get the error message:
i ⊔ i != i of type ℕ
when checking that the inferred type of an application
MyType (i ⊔ i)
matches the expected type
MyType i
I know I can prove i ⊔ i ≡ i, but I don't know how to give that proof to the type system in order to get this to resolve.
How do I get this to compile?
You can use subst from Relation.Binary.PropositionalEquality.
You give it:
the proof that i ⊔ i ≡ i
the dependent type that should be transformed with the proof, in your case MyType
the term to be transformed, in your case combine {i} {i} (cons i) (cons i)
Or you can use the rewrite keyword as well on your proof, which is usually to be preferred.
Here is an (artificial) example of both possibilities applied on vector concatenation:
module ConsVec where
open import Data.Vec
open import Data.Nat
open import Data.Nat.Properties
open import Relation.Binary.PropositionalEquality
_++₁_ : ∀ {a} {A : Set a} {m n} → Vec A m → Vec A n → Vec A (n + m)
_++₁_ {m = m} {n} v₁ v₂ = subst (Vec _) (+-comm m n) (v₁ ++ v₂)
_++₂_ : ∀ {a} {A : Set a} {m n} → Vec A m → Vec A n → Vec A (n + m)
_++₂_ {m = m} {n} v₁ v₂ rewrite sym (+-comm m n) = v₁ ++ v₂
What is wrong with this code?
EDIT:
I'm sending all the code including dependencies, imports, flags, etc.
I can't figure out where the error might be. I would be very grateful if someone could direct me how to fix this error.
{-# OPTIONS --type-in-type --without-K #-}
module Basic where
Type = Set
data Path {A : Type} : A → A → Type where
id : {M : A} → Path M M
_≃_ : {A : Type} → A → A → Type
_≃_ = Path
infix 9 _≃_
ap : {A B : Type} {M N : A}
(f : A → B) → Path{A} M N → Path{B} (f M) (f N)
ap f id = id
ap≃ : ∀ {A} {B : A → Type} {f g : (x : A) → B x}
→ Path f g → {x : A} → Path (f x) (g x)
ap≃ α {x} = ap (\ f → f x) α
postulate
λ≃ : ∀ {A} {B : A → Type} {f g : (x : A) → B x}
→ ((x : A) → Path (f x) (g x))
I'm getting this error:
Failed to solve the following constraints:
Has bigger sort: _44
piSort _25 (λ _ → Set) = Set
Has bigger sort: _25
Any help?
I didn't get quite the same error, but I got the file to check by annotating A with type Type in the type of λ≃:
postulate
λ≃ : ∀ {A : Type} {B : A → Type} {f g : (x : A) → B x}
→ ((x : A) → Path (f x) (g x))
The error I saw comes about because Agda will usually assume that you might want to use universe polymorphism, and there happens to be nothing else in the type of λ≃ that constrains A to the lowest universe Type.
In the Agda standard library, we have RawMonad, RawApplicative, etc..
RawMonad : ∀ {f} → (Set f → Set f) → Set _
RawMonad M = RawIMonad {I = ⊤} (λ _ _ → M)
RawMonadZero : ∀ {f} → (Set f → Set f) → Set _
RawMonadZero M = RawIMonadZero {I = ⊤} (λ _ _ → M)
RawMonadPlus : ∀ {f} → (Set f → Set f) → Set _
RawMonadPlus M = RawIMonadPlus {I = ⊤} (λ _ _ → M)
Why do they start with Raw? Are there Monad or Applicative in Agda?
I've been told by Nils Anders Danielsson (their author, I suspect) once that it's because they don't contain proofs of the respective laws.
AFAIK, the Agda standard library doesn't have versions of these that do contain such proofs, but you can roll your own if you like.
Recently I made a type for finite sets in Agda with the following implementation:
open import Relation.Nullary
open import Relation.Nullary.Negation
open import Data.Empty
open import Data.Unit
open import Relation.Binary.PropositionalEquality
open import Data.Nat
suc-inj : (n m : ℕ) → (suc n) ≡ (suc m) → n ≡ m
suc-inj n .n refl = refl
record Eq (A : Set) : Set₁ where
constructor mkEqInst
field
_decide≡_ : (a b : A) → Dec (a ≡ b)
open Eq {{...}}
mutual
data FinSet (A : Set) {{_ : Eq A }} : Set where
ε : FinSet A
_&_ : (a : A) → (X : FinSet A) → .{ p : ¬ (a ∈ X)} → FinSet A
_∈_ : {A : Set} → {{p : Eq A}} → (a : A) → FinSet A → Set
a ∈ ε = ⊥
a ∈ (b & B) with (a decide≡ b)
... | yes _ = ⊤
... | no _ = a ∈ B
_∉_ : {A : Set} → {{p : Eq A}} → (a : A) → FinSet A → Set
_∉_ a X = ¬ (a ∈ X)
decide∈ : {A : Set} → {{_ : Eq A}} → (a : A) → (X : FinSet A) → Dec (a ∈ X)
decide∈ a ε = no (λ z → z)
decide∈ a (b & X) with (a decide≡ b)
decide∈ a (b & X) | yes _ = yes tt
... | no _ = decide∈ a X
decide∉ : {A : Set} → {{_ : Eq A}} → (a : A) → (X : FinSet A) → Dec (a ∉ X)
decide∉ a X = ¬? (decide∈ a X)
instance
eqℕ : Eq ℕ
eqℕ = mkEqInst decide
where decide : (a b : ℕ) → Dec (a ≡ b)
decide zero zero = yes refl
decide zero (suc b) = no (λ ())
decide (suc a) zero = no (λ ())
decide (suc a) (suc b) with (decide a b)
... | yes p = yes (cong suc p)
... | no p = no (λ x → p ((suc-inj a b) x))
However, when I test this type out with the following:
test : FinSet ℕ
test = _&_ zero ε
Agda for some reason can't infer the implicit argument of type ¬ ⊥! However, auto of course finds the proof of this trivial proposition: λ x → x : ¬ ⊥.
My question is this: Since I've marked the implicit proof as irrelevant, why can't Agda simply run auto to find the proof of ¬ ⊥ during type checking? Presumably, whenever filling in other implicit arguments, it might matter exactly what proof Agda finda, so it shouldn't just run auto, but if the proof has been marked irrelevant, like it my case, why can't Agda find a proof?
Note: I have a better implementation of this, where I implement ∉ directly, and Agda can find the relevant proof, but I want to understand in general why Agda can't automatically find these sorts of proofs for implicit arguments. Is there any way in the current implementation of Agda to get these "auto implicits" like I want here? Or is there some theoretical reason why this would be a bad idea?
There's no fundamental reason why irrelevant arguments couldn't be solved by proof search, however the fear is that in many cases it would be slow and/or not find a solution.
A more user-directed thing would be to allow the user to specify that a certain argument should be inferred using a specific tactic, but that has not been implemented either. In your case you would provide a tactic that tries to solve the goal with (\ x -> x).
If you give a more direct definition of ∉, then the implicit argument gets type ⊤ instead of ¬ ⊥. Agda can fill in arguments of type ⊤ automatically by eta-expansion, so your code just works:
open import Relation.Nullary
open import Relation.Nullary.Negation
open import Data.Empty
open import Data.Unit
open import Relation.Binary.PropositionalEquality
open import Data.Nat
suc-inj : (n m : ℕ) → (suc n) ≡ (suc m) → n ≡ m
suc-inj n .n refl = refl
record Eq (A : Set) : Set₁ where
constructor mkEqInst
field
_decide≡_ : (a b : A) → Dec (a ≡ b)
open Eq {{...}}
mutual
data FinSet (A : Set) {{_ : Eq A}} : Set where
ε : FinSet A
_&_ : (a : A) → (X : FinSet A) → .{p : (a ∉ X)} → FinSet A
_∉_ : {A : Set} → {{p : Eq A}} → (a : A) → FinSet A → Set
a ∉ ε = ⊤
a ∉ (b & X) with (a decide≡ b)
... | yes _ = ⊥
... | no _ = a ∉ X
decide∉ : {A : Set} → {{_ : Eq A}} → (a : A) → (X : FinSet A) → Dec (a ∉ X)
decide∉ a ε = yes tt
decide∉ a (b & X) with (a decide≡ b)
... | yes _ = no (λ z → z)
... | no _ = decide∉ a X
instance
eqℕ : Eq ℕ
eqℕ = mkEqInst decide
where decide : (a b : ℕ) → Dec (a ≡ b)
decide zero zero = yes refl
decide zero (suc b) = no (λ ())
decide (suc a) zero = no (λ ())
decide (suc a) (suc b) with (decide a b)
... | yes p = yes (cong suc p)
... | no p = no (λ x → p ((suc-inj a b) x))
test : FinSet ℕ
test = _&_ zero ε
We can implement a delimited continuation monad in Agda rather easily.
There is, however, no need to, as the Agda "standard library" has an implementation of a delimited continuation monad. What confuses me about this implementation, though, is the addition of an extra parameter to the DCont type.
DCont : ∀ {i f} {I : Set i} → (I → Set f) → IFun I f
DCont K = DContT K Identity
My question is: why is the extra parameter K there? And how would I use the DContIMonadDCont instance? Can I open it in such a way that I'll get something akin to the below reference implementation in (global) scope?
All my attempts to use it are leading to unsolvable metas.
Reference implementation of delimited continuations not using the Agda "standard library".
DCont : Set → Set → Set → Set
DCont r i a = (a → i) → r
return : ∀ {r a} → a → DCont r r a
return x = λ k → k x
_>>=_ : ∀ {r i j a b} → DCont r i a → (a → DCont i j b) → DCont r j b
c >>= f = λ k → c (λ x → f x k)
join : ∀ {r i j a} → DCont r i (DCont i j a) → DCont r j a
join c = c >>= id
shift : ∀ {r o i j a} → ((a → DCont i i o) → DCont r j j) → DCont r o a
shift f = λ k → f (λ x → λ k′ → k′ (k x)) id
reset : ∀ {r i a} → DCont a i i → DCont r r a
reset a = λ k → k (a id)
Let me answer your second and third questions first. Looking at how DContT is defined:
DContT K M r₂ r₁ a = (a → M (K r₁)) → M (K r₂)
We can recover the requested definition by specifying M = id and K = id (M also has to be a monad, but we have the Identity monad). DCont already fixes M to be id, so we are left with K.
import Category.Monad.Continuation as Cont
open import Function
DCont : Set → Set → Set → Set
DCont = Cont.DCont id
Now, we can open the RawIMonadDCont module provided we have an instance of the corresponding record. And luckily, we do: Category.Monad.Continuation has one such record under the name DContIMonadDCont.
module ContM {ℓ} =
Cont.RawIMonadDCont (Cont.DContIMonadDCont {f = ℓ} id)
And that's it. Let's make sure the required operations are really there:
return : ∀ {r a} → a → DCont r r a
return = ContM.return
_>>=_ : ∀ {r i j a b} → DCont r i a → (a → DCont i j b) → DCont r j b
_>>=_ = ContM._>>=_
join : ∀ {r i j a} → DCont r i (DCont i j a) → DCont r j a
join = ContM.join
shift : ∀ {r o i j a} → ((a → DCont i i o) → DCont r j j) → DCont r o a
shift = ContM.shift
reset : ∀ {r i a} → DCont a i i → DCont r r a
reset = ContM.reset
And indeed, this typechecks. You can also check if the implementation matches. For example, using C-c C-n (normalize) on shift, we get:
λ {.r} {.o} {.i} {.j} {.a} e k → e (λ a f → f (k a)) (λ x → x)
Modulo renaming and some implicit parameters, this is exactly implementation of the shift in your question.
Now the first question. The extra parameter is there to allow additional dependency on the indices. I haven't used delimited continuations in this way, so let me reach for an example somewhere else. Consider this indexed writer:
open import Data.Product
IWriter : {I : Set} (K : I → I → Set) (i j : I) → Set → Set
IWriter K i j A = A × K i j
If we have some sort of indexed monoid, we can write a monad instance for IWriter:
record IMonoid {I : Set} (K : I → I → Set) : Set where
field
ε : ∀ {i} → K i i
_∙_ : ∀ {i j k} → K i j → K j k → K i k
module IWriterMonad {I} {K : I → I → Set} (mon : IMonoid K) where
open IMonoid mon
return : ∀ {A} {i : I} →
A → IWriter K i i A
return a = a , ε
_>>=_ : ∀ {A B} {i j k : I} →
IWriter K i j A → (A → IWriter K j k B) → IWriter K i k B
(a , w₁) >>= f with f a
... | (b , w₂) = b , w₁ ∙ w₂
Now, how is this useful? Imagine you wanted to use the writer to produce a message log or something of the same ilk. With usual boring lists, this is not a problem; but if you wanted to use vectors, you are stuck. How to express that type of the log can change? With the indexed version, you could do something like this:
open import Data.Nat
open import Data.Unit
open import Data.Vec
hiding (_>>=_)
open import Function
K : ℕ → ℕ → Set
K i j = Vec ℕ i → Vec ℕ j
K-m : IMonoid K
K-m = record
{ ε = id
; _∙_ = λ f g → g ∘ f
}
open IWriterMonad K-m
tell : ∀ {i j} → Vec ℕ i → IWriter K j (i + j) ⊤
tell v = _ , _++_ v
test : ∀ {i} → IWriter K i (5 + i) ⊤
test =
tell [] >>= λ _ →
tell (4 ∷ 5 ∷ []) >>= λ _ →
tell (1 ∷ 2 ∷ 3 ∷ [])
Well, that was a lot of (ad-hoc) code to make a point. I haven't given it much thought, so I'm fairly sure there's nicer/more principled approach, but it illustrates that such dependency allows your code to be more expressive.
Now, you could apply the same thing to DCont, for example:
test : Cont.DCont (Vec ℕ) 2 3 ℕ
test c = tail (c 2)
If we apply the definitions, the type reduces to (ℕ → Vec ℕ 3) → Vec ℕ 2. Not very convincing example, I know. But perhaps you can some up with something more useful now that you know what this parameter does.