Specialize `Map` typeclass into `PartialMap` typeclass - typeclass

I've defined a pair of typeclasses called Map and PartialMap, with the obvious rules for such data structures. In particular, they differ only in whether they range over some V or option V.
It is clear to me that PartialMap is essentially a special case of Map. However, I'm not sure how to encode that.
Class Map M K V: Type := {
get: M K V -> K -> V;
set: M K V -> K -> V -> M K V;
map_get_set_idem: forall (m: M K V) (k: K) (v: V), get (set m k v) k = v;
map_get_set_comm: forall (m: M K V) (k1 k2: K) (v: V), ~(k1 = k2) -> get (set m k1 v) k2 = get m k2;
}.
Class PartialMap M K V: Type := {
pget: M K V -> K -> option V;
pset: M K V -> K -> option V -> M K V;
pmap_pget_pset_idem: forall (m: M K V) (k: K) (v: option V), pget (pset m k v) k = v;
pmap_pget_pset_comm: forall (m: M K V) (k1 k2: K) (v: option V), ~(k1 = k2) -> pget (pset m k1 v) k2 = pget m k2;
}.

Turns out that parameterizing M by K and V is totally superfluous.
Class Map M K V: Type := {
get: M -> K -> V;
set: M -> K -> V -> M;
map_get_set_idem: forall m k v, get (set m k v) k = v;
map_get_set_comm: forall m k1 k2 v, ~(k1 = k2) -> get (set m k1 v) k2 = get m k2;
}.
Class PartialMap M K V: Type := {
PartialMapIsMap :> Map M K (option V)
}.

Related

Calling one-parameter function with two arguments?

I have this code:
type Sym = (string * float) list
let rec lookup v = function
| (v', k) :: vtab -> if v = v' then k else lookup v vtab
| (_ : Sym) -> failwith ("unbound: " + v)
To me, it looks like that lookup takes one argument v. But then we do lookup v vtab - now it seems like two arguments are being passed to lookup? How can this be valid when lookup only takes one argument?
It does take two parameters. The first one is v, the second one comes from function.
In F# function is syntactic sugar for match. More specifically, the word function means fun x -> match x with.
So you can read your code as:
let rec lookup v = fun x -> match x with
| (v', k) :: vtab -> if v = v' then k else lookup v vtab
| (_ : Sym) -> failwith ("unbound: " + v)
Which in turn is the same as:
let rec lookup v x = match x with
| (v', k) :: vtab -> if v = v' then k else lookup v vtab
| (_ : Sym) -> failwith ("unbound: " + v)

`with f x` matches `false`, but cannot construct `f x == false`

A piece of code here:
-- transitivity
trans : {A : Set} {x y z : A} -> x == y -> y == z -> x == z
trans refl refl = refl
union-pair' : {A : Set} -> (m n : S {A}) -> (x : A) ->
(ismember (set-union (set-pair m n)) x) == (ismember (union m n) x)
union-pair' m n x with ismember m x | ismember n x | ismember (set-union (set-pair m n)) x
union-pair' : {A : Set} -> (m n : S {A}) -> (x : A) ->
(ismember (set-union (set-pair m n)) x) == (ismember (union m n) x)
union-pair' m n x with ismember m x | ismember n x | ismember (set-union (set-pair m n)) x
... | false | false | false = trans {x = ismember (set-union (set-pair m n)) x} {y = false}
refl -- line #102
(union-match m n x)
-- more code available on request, although I can't see why that would matter
produces an error:
code.agda:102,54-58
(ismember (set-union (set-pair m n)) x) != false of type Bool
when checking that the expression refl has type
ismember (set-union (set-pair m n)) x == false
I have a with-statement, which establishes exactly the fact that ismember (set-union (set-pair m n)) x is false. Why can it not establish that it is false?
Ok, I can even see some known issues https://agda.readthedocs.io/en/v2.5.2/language/with-abstraction.html#ill-typed-with-abstractions but still none the wiser as to how to pattern match then.
It looks like you need to remember the fact that the following expression
ismember (set-union (set-pair m n)) x
is indeed equal to
false
This is a very common problem that comes from the way the 'with' construct works. By default, you don't have access to the proof element that connects the element on which you pattern match with the result of the pattern matching, that is, in your example, an element of type:
ismember (set-union (set-pair m n)) x == false
In order to get an element of this type, you need to use the 'inspect' idiom that is defined alongside the propositional equality in the standard library. More concretely, this means you'll have to add a new element to your pattern matching as follows:
... | ismember (set-union (set-pair m n)) x | inspect (ismember (set-union (set-pair m n)) x
This will result in you having access both to 'false' and the proof element you require. For more information about the inspect idiom, see :
The wiki page on the with-abtraction : https://agda.readthedocs.io/en/v2.6.0.1/language/with-abstraction.html
The file PropositionalEquality.agda in the standard library, which provides the idiom as well as a quick description of how to use it
The file README/Inspect.agda in the standard library as well which provides a complete example on how and when to use the inspect idiom

LaTeX, sloped boxes

I'd like to make a Find-A-Word for the library wall.
The solution (also for the wall) requires a box, enclosing the word.
Horizontal/vertical boxes are no problem. Sloped (slanted?) boxes are what's the problem.\I envisage a command like
\makebox (length, breadth, angle, co-ordinates of left-lower corner)
It may be that this has been done before.
Has anyone any suggestions?
William.
Using tikz and the tikzmarks library:
\documentclass{article}
\usepackage[hmargin=4cm]{geometry}
\usepackage{tikz}
\usetikzlibrary{tikzmark}
\begin{document}
\ttfamily
\noindent
\tikzmark{a:start}w d e w e r n \tikzmark{b:start}b v c w o i q\tikzmark{b:stop} v o i q t u h n r g j q v r o e q i o n j v k w
o q p i n t o j v k m o q e i n g k m f o r q e p i n k f m p i g n o j k m
f \tikzmark{c:start}v e p o q i o n j r g k m l e v q n b g j k v m e q n b o j g k v l m e q
n b j g f k l e m v q n j g k e m l v q n g j r f e l v q n j g f l k q g j
n\tikzmark{a:stop} v q e\tikzmark{c:stop} n p m k w g j k n e k e m l v q n g j r f e l v q n j g f l k q g j
\begin{tikzpicture}[remember picture, overlay]
\draw[red] ([shift={(0,1.5ex)}]pic cs:a:start) rectangle (pic cs:a:stop);
\draw[red] ([shift={(0,1.5ex)}]pic cs:b:start) rectangle (pic cs:b:stop);
\draw[red,rotate=45] ([shift={(1.5ex,1.5ex)}]pic cs:c:start) rectangle ([shift={(-0.5ex,0ex)}]pic cs:c:stop);
\end{tikzpicture}
\end{document}

Erlang Maps : get keys that has the same value

I have a {H,VV} pair and I want to compare this pair against the rest of the Map to find other key that has the same value.
I tried this:
check(H,Map)->
VV=maps:get(H,Map),
Fun = fun(K,V) when H =/= K, V=:=VV->
io:format("~p~p~n",[H,K])
end,
maps:map(Fun,Map).
it compiles but raise error "function_clause"
Any ideas how to implement this?
The function you're passing to maps:map/2 does not handle the H key nor any value not equal to VV. Try this instead:
check(H,Map)->
VV=maps:get(H,Map),
Fun = fun(K,V) when H =/= K, V=:=VV->
io:format("~p:~p~n",[H,K]),
V;
(_,V) -> V
end,
maps:map(Fun,Map).
I think you're better off using maps:fold/3 for this case, though, since you're not trying to create a new map, but rather just want to know the other keys with the same value as H. Consider the approach below:
check(H, Map) ->
VV = maps:get(H,Map),
maps:fold(fun(K,V,Acc) when K /= H, V =:= VV ->
[K|Acc];
(_,_,Acc) ->
Acc
end, [], Map).
This version returns a list of keys that have the same value as H in Map.
There are list comprehension solutions for this as well:
VV = maps:get(H,Map),
[ K || K <- maps:keys(Map), K =/= H, VV =:= maps:get(K, Map) ].
Or
VV = maps:get(H,Map),
[ K || {K, V} <- maps:to_list(Map), K =/= H, V =:= VV ].

How does one prove a type of the form (a | b) in agda?

In thinking about:
In Agda is it possible to define a datatype that has equations?
I was playing with the following datatype:
data Int : Set where
Z : Int
S : Int -> Int
P : Int -> Int
The above is a poor definition of Integers, and the answers in the above give a way around this. However, one can define a reduction on the above Int type that might be useful.
normalize : Int -> Int
normalize Z = Z
normalize (S n) with normalize n
... | P m = m
... | m = S m
normalize (P n) with normalize n
... | S m = m
... | m = P m
The thing that needs to be proved is:
idempotent : (n : Int) -> normalize n \== normalize (normalize n)
When you expand the cases out, you get for example
idempotent (P n) = ?
The goal for the hole has type
(normalize (P n) | normalize n) \== normalize (normalize (P n) | normalize n)
And I haven't seen this "|" before, nor do I know how to produce a proof of a type involving them. The proof needs to pattern match,for example,
idempotent (P n) with inspect (normalize n)
... (S m) with-\== = ?
... m with-\== = ?
But here the hole for the second case still has a "|" in it. So I am a bit confused.
-------- EDIT ---------------
It would be helpful to prove a simpler statement:
normLemma : (n m : NZ) -> normalize n \== P m -> normalize (S n) \== m
The "on paper" proof is rather straightforward. Assuming normalize n = P m, consider
normalize (S n) = case normalize n of
P k -> k
x -> S x
But normalize n is assumed to be P m, hence normalize (S n) = k. Then k = m, since normalize n = P m = P k which implies m = k. Thus normalize (S n) = m.
User Vitus proposed to use normal forms.
If we have these two functions:
normalForm : ∀ n -> NormalForm (normalize n)
idempotent' : ∀ {n} -> NormalForm n -> normalize n ≡ n
then we can easily compose them to obtain the result we need:
idempotent : ∀ n -> normalize (normalize n) ≡ normalize n
idempotent = idempotent' ∘ normalForm
Here is the definition of normal forms:
data NormalForm : Int -> Set where
NZ : NormalForm Z
NSZ : NormalForm (S Z)
NPZ : NormalForm (P Z)
NSS : ∀ {n} -> NormalForm (S n) -> NormalForm (S (S n))
NPP : ∀ {n} -> NormalForm (P n) -> NormalForm (P (P n))
I.e. only terms like S (S ... (S Z)... and P (P ... (P Z)...) are in the normal form.
And proofs are rather straightforward:
normalForm : ∀ n -> NormalForm (normalize n)
normalForm Z = NZ
normalForm (S n) with normalize n | normalForm n
... | Z | nf = NSZ
... | S _ | nf = NSS nf
... | P ._ | NPZ = NZ
... | P ._ | NPP nf = nf
normalForm (P n) with normalize n | normalForm n
... | Z | nf = NPZ
... | S ._ | NSZ = NZ
... | S ._ | NSS nf = nf
... | P _ | nf = NPP nf
idempotent' : ∀ {n} -> NormalForm n -> normalize n ≡ n
idempotent' NZ = refl
idempotent' NSZ = refl
idempotent' NPZ = refl
idempotent' (NSS p) rewrite idempotent' p = refl
idempotent' (NPP p) rewrite idempotent' p = refl
The whole code: https://gist.github.com/flickyfrans/f2c7d5413b3657a94950#file-another-one
idempotent : (n : Int) -> normalize (normalize n) ≡ normalize n
idempotent Z = refl
idempotent (S n) with normalize n | inspect normalize n
... | Z | _ = refl
... | S m | [ p ] = {!!}
... | P m | [ p ] = {!!}
Context in the first hole is
Goal: (normalize (S (S m)) | (normalize (S m) | normalize m)) ≡
S (S m)
————————————————————————————————————————————————————————————
p : normalize n ≡ S m
m : Int
n : Int
(normalize (S (S m)) | (normalize (S m) | normalize m)) ≡ S (S m) is just an expanded version of normalize (S (S m)). So we can rewrite the context a bit:
Goal: normalize (S (S m)) ≡ S (S m)
————————————————————————————————————————————————————————————
p : normalize n ≡ S m
m : Int
n : Int
Due to the definition of the normalize function
normalize (S n) with normalize n
... | P m = m
... | m = S m
normalize (S n) ≡ S (normalize n), if normalize n doesn't contain Ps.
If we have an equation like normalize n ≡ S m, than m is already normalized and doesn't contain Ps. But if m doesn't contain Ps, so and normalize m. So we have normalize (S m) ≡ S (normalize m).
Let's prove a little more general lemma:
normalize-S : ∀ n {m} -> normalize n ≡ S m -> ∀ i -> normalize (m ‵add‵ i) ≡ m ‵add‵ i
where ‵add‵ is
_‵add‵_ : Int -> ℕ -> Int
n ‵add‵ 0 = n
n ‵add‵ (suc i) = S (n ‵add‵ i)
normalize-S states, that if m doesn't contain Ps, than this holds:
normalize (S (S ... (S m)...)) ≡ S (S ... (S (normalize m))...)
Here is a proof:
normalize-S : ∀ n {m} -> normalize n ≡ S m -> ∀ i -> normalize (m ‵add‵ i) ≡ m ‵add‵ i
normalize-S Z () i
normalize-S (S n) p i with normalize n | inspect normalize n
normalize-S (S n) refl i | Z | _ = {!!}
normalize-S (S n) refl i | S m | [ q ] = {!!}
normalize-S (S n) refl i | P (S m) | [ q ] = {!!}
normalize-S (P n) p i with normalize n | inspect normalize n
normalize-S (P n) () i | Z | _
normalize-S (P n) refl i | S (S m) | [ q ] = {!!}
normalize-S (P n) () i | P _ | _
Context in the first hole is
Goal: normalize (Z ‵add‵ i) ≡ Z ‵add‵ i
————————————————————————————————————————————————————————————
i : ℕ
.w : Reveal .Data.Unit.Core.hide normalize n is Z
n : Int
I.e. normalize (S (S ... (S Z)...)) ≡ S (S ... (S Z)...). We can easily prove it:
normalize-add : ∀ i -> normalize (Z ‵add‵ i) ≡ Z ‵add‵ i
normalize-add 0 = refl
normalize-add (suc i) rewrite normalize-add i with i
... | 0 = refl
... | suc _ = refl
So we can fill the first hole with normalize-add i.
Context in the second hole is
Goal: normalize (S m ‵add‵ i) ≡ S m ‵add‵ i
————————————————————————————————————————————————————————————
i : ℕ
q : .Data.Unit.Core.reveal (.Data.Unit.Core.hide normalize n) ≡ S m
m : Int
n : Int
While normalize-S n q (suc i) has this type:
(normalize (S (m ‵add‵ i)) | normalize (m ‵add‵ i)) ≡ S (m ‵add‵ i)
Or, shortly, normalize (S (m ‵add‵ i)) ≡ S (m ‵add‵ i). So we need to replace S m ‵add‵ i with S (m ‵add‵ i):
inj-add : ∀ n i -> S n ‵add‵ i ≡ S (n ‵add‵ i)
inj-add n 0 = refl
inj-add n (suc i) = cong S (inj-add n i)
And now we can write
normalize-S (S n) refl i | S m | [ q ] rewrite inj-add m i = normalize-S n q (suc i)
Context in the third hole is
Goal: normalize (m ‵add‵ i) ≡ m ‵add‵ i
————————————————————————————————————————————————————————————
i : ℕ
q : .Data.Unit.Core.reveal (.Data.Unit.Core.hide normalize n) ≡
P (S m)
m : Int
n : Int
normalize-P n q 0 gives us normalize (S m) ≡ S m where normalize-P is dual of normalize-S and has this type:
normalize-P : ∀ n {m} -> normalize n ≡ P m -> ∀ i -> normalize (m ‵sub‵ i) ≡ m ‵sub‵ i
We can apply normalize-S to something, that has type normalize (S m) ≡ S m: normalize-S (S m) (normalize-P n q 0) i. This expression has precisely the type we want. So we can write
normalize-S (S n) refl i | P (S m) | [ q ] = normalize-S (S m) (normalize-P n q 0) i
The fourth hole is similar to the third:
normalize-S (P n) refl i | S (S m) | [ q ] = normalize-S (S m) (normalize-S n q 0) i
There is a problem with this holes: Agda doesn't see, that normalize-S (S m) _ _ terminates, since S m is not syntactically smaller than S n. It's possible however to convience Agda by using well-founded recursion.
Having all this stuff we can easily proof the idempotent theorem:
idempotent : (n : Int) -> normalize (normalize n) ≡ normalize n
idempotent Z = refl
idempotent (S n) with normalize n | inspect normalize n
... | Z | _ = refl
... | S m | [ p ] = normalize-S n p 2
... | P m | [ p ] = normalize-P n p 0
idempotent (P n) with normalize n | inspect normalize n
... | Z | _ = refl
... | S m | [ p ] = normalize-S n p 0
... | P m | [ p ] = normalize-P n p 2
Here is the code: https://gist.github.com/flickyfrans/f2c7d5413b3657a94950
There are both versions: with the {-# TERMINATING #-} pragma and without.
EDIT
idempotent is simply
idempotent : ∀ n -> normalize (normalize n) ≡ normalize n
idempotent n with normalize n | inspect normalize n
... | Z | _ = refl
... | S _ | [ p ] = normalize-S n p 1
... | P _ | [ p ] = normalize-P n p 1

Resources