"rewriting did not change type" error for visually same types - functor

I wrote a short function:
swapMaybe : Monad m => Maybe (m a) -> m (Maybe a)
swapMaybe Nothing = pure Nothing
swapMaybe (Just x) = map Just x
Then I tried to prove one of its properties:
import Interfaces.Verified
swapMaybePreservesMap : VerifiedMonad m => (g : a -> b) -> (x : Maybe (m a)) ->
swapMaybe (map (map g) x) = map (map g) (swapMaybe x)
swapMaybePreservesMap g Nothing = ?hswapMaybePreservesMapNothing
swapMaybePreservesMap g (Just x) = ?hswapMaybePreservesMapJust
(functorComposition x g Just)
(functorComposition x Just (map g))
:t hswapMaybePreservesMapJust gives following type:
a : Type
b : Type
g : a -> b
m : Type -> Type
x : m a
constraint : VerifiedMonad m
--------------------------------------
hswapMaybePreservesMapJust : (map (\x1 => Just (g x1)) x = map Just (map g x)) ->
(map (\x1 => Just (g x1)) x = map (\meth => Prelude.Maybe implementation of Prelude.Functor.Functor, method map g meth) (map Just x)) ->
map Just (map g x) = map (\meth => Prelude.Maybe implementation of Prelude.Functor.Functor, method map g meth) (map Just x)
Visually the same left side map (\x1 => Just (g x1)) x of both parameters of hswapMaybePreservesMapJust looks promising for applying rewrite.
However, it fails:
swapMaybePreservesMap g (Just x) = rewrite (functorComposition x g Just) in
(functorComposition x Just (map g))
The error:
When checking right hand side of swapMaybePreservesMap with expected type
swapMaybe (map (map g) (Just x)) = map (map g) (swapMaybe (Just x))
rewriting map (\x1 => Just (g x1)) x to map Just (map g x) did not change type map Just (map g x) =
map (\meth => Prelude.Maybe implementation of Prelude.Functor.Functor, method map g meth) (map Just x)
I checked this question and tried to explicitly specify the result type with the, moving rewrite parameters to let and eta-expand map g. Also without success, though:
swapEq : {x : a} -> {y : a} -> x = y -> y = x
swapEq eq = rewrite eq in Refl
swapMaybePreservesMap : VerifiedMonad n => (g : a -> b) -> (x : Maybe (n a)) ->
swapMaybe (map (\z => map g z) x) = map (\z => map g z) (swapMaybe x)
swapMaybePreservesMap g Nothing = ?hswapMaybePreservesMapNothing
swapMaybePreservesMap g xx#(Just x) = let
pr1 = (swapEq $ functorComposition x g Just)
pr2 = (functorComposition x Just (\z => map g z))
in the (swapMaybe (map (\z => map g z) xx) = map (\z => map g z) (swapMaybe xx))
(rewrite pr1 in pr2)
... with following message:
When checking right hand side of swapMaybePreservesMap with expected type
swapMaybe (map (\z => map g z) (Just x)) = map (\z8 => map g z8) (swapMaybe (Just x))
When checking argument value to function Prelude.Basics.the:
rewriting map Just (map g x) to map (\x1 => Just (g x1)) x did not change type map Just (map g x) =
map (\z11 => Prelude.Maybe implementation of Prelude.Functor.Functor, method map g z11) (map Just x)
As I've read in the docs:
rewrite prf in expr
If we have prf : x = y, and the required type for expr is some
property of x, the rewrite ... in syntax will search for x in the
required type of expr and replace it with y.
Why rewrite is not working in this case?
Is it because of actually different values at the left side of the parameters (maybe some implicit parameters are not shown) or somethhing else? Maybe it's better to apply some Elab tactics script explicitly?

Finally I found the reason - it's different type constraints in swapMaybe and swapMaybePreservesMap. Following implementation gives a clear error:
swapMaybePreservesMap : VerifiedMonad m => (g : a -> b) -> (x : Maybe (m a)) ->
swapMaybe (map (map g) x) = map (map g) (swapMaybe x)
swapMaybePreservesMap g Nothing = ?outOfScope
swapMaybePreservesMap g (Just x) = trans
(sym $ functorComposition x g Just)
(functorComposition x Just (map g))
The message:
When checking right hand side of swapMaybePreservesMap with expected type
swapMaybe (map (map g) (Just x)) = map (map g) (swapMaybe (Just x))
When checking an application of function trans:
Type mismatch between
map (map g . Just) x = (map (map g) . map Just) x (Type of functorComposition x Just (map g))
and
map (\x1 => Just (g x1)) x = map (\meth => Prelude.Maybe implementation of Prelude.Functor.Functor, method map g meth) (map Just x) (Expected type)
Specifically:
Type mismatch between
map (map g) (map Just x)
and
map (\meth => Prelude.Maybe implementation of Prelude.Functor.Functor, method map g meth) (map Just x)
Applying VerifiedMonad type constraint to swapMaybe instead of Monad makes type checker happy (with swapMaybePreservesMap implementation from above):
swapMaybe : Monad m => Maybe (m a) -> m (Maybe a)
swapMaybe Nothing = pure Nothing
swapMaybe (Just x) = map Just x
However, it'd be nice to prove some property of a function, working with some Monad, which holds only for VerifiedMonad.

Related

`or` function in Scheme misbehaving

I am trying to write an or function in Scheme
(define or
(lambda (p q) p p q))
If I do (or #t #f) I get #f.
What is the problem in what I am doing?
I saw λpq.ppq in a video on youTube.
The correct Lambda Calculus definitions are
(define or (lambda (p q) (p p q))) ; (or p q) = {p AND p} OR {{NOT p} AND q}
(define xor (lambda (p q) (p (not q) q))) ; (xor p q) = {p AND {NOT q}} OR {{NOT p} AND q}
(define not (lambda (t) (lambda (p q) (t q p)))) ; ((not t) p q) = (t q p)
(note the parens!). But #t and #f won't work with these. They expect
(define true (lambda (p q) p)) ; (true p q) = p
(define false (lambda (p q) q)) ; (false p q) = q
You can check it with
((or true false) #t #f) ; #t
((xor false false) #t #f) ; #f
((xor true false) #t #f) ; #t
With your definition there's a set of parentheses missing:
(define or (lambda (p q) p p q ))
; ^^ ^^
It reduces as:
(or #t #f)
=
(let ([p #t] [q #f])
p
p
q )
=
(let ([p #t] [q #f])
q )
=
#f
To cause an application of p to p and q we need to enclose the form in parentheses, like this: (p p q). Without them you just have three consecutive expressions, three variables, and only the last one's value is returned, as is, as the overall result. Which is the value of q. Which is #f.

Nested calling in random order

How do I make a randApply function that take a seed x and a list of functions (of type a -> a, says f, g, h) that return a random one from permutations of f, g, h
f (g (h x))
f (h (g x))
g (f (h x))
g (h (f x))
h (f (g x))
h (g (f x))
How do I define such randApply :: a -> [a -> a] -> a?
First, you are not going to make a function randApply :: a -> [a -> a] -> a with a random value. Instead you define one randApply :: a -> [a -> a] -> IO a. Learn Monad at https://wiki.haskell.org/Monad.
2 step for your solution:
Shuffle given functions
Apply random function list to the seed one by one
Shuffle:
shuffle :: [a] -> IO [a]
shuffle [] = return []
shuffle xs = do nRand <- randomRIO (0, length xs - 1)
rest <- shuffle (erase nRand xs)
return (xs !! nRand : rest)
erase :: Int -> [a] -> [a]
erase n xs = take n xs ++ drop (n+1) xs
Check more effiecient shuffle program at https://wiki.haskell.org/Random_shuffle.
Apply to the seed one by one:
seqApply :: a -> [a -> a] -> a
seqApply x [] = x
seqApply x (f : fList) = seqApply (f x) fList
randApply you want:
randApply :: a -> [a -> a] -> IO a
randApply x fList = do randList <- shuffle fList
return (seqApply x randList)

How do I implement Extended Euclidean algorithm?

How can I implement the Extended Euclidean algorithm? Here's my first attempt:
(define ex-gcd a b
; gcd(a,b) = a * x+ b * y
; gcd(a,b)-> always will be 1
output: (x.y)
)
The algorithm is right here in Wikipedia, you just have to adapt it to only return Bézout coefficients, the car part of the returned cons-cell will be x, and the cdr will be y:
(define (extended-gcd a b)
(let loop ([s 0] [t 1] [r b]
[old-s 1] [old-t 0] [old-r a])
(if (zero? r)
(cons old-s old-t)
(let ((q (quotient old-r r)))
(loop (- old-s (* q s))
(- old-t (* q t))
(- old-r (* q r))
s t r)))))
It's easy to test it using Bézout's identity, use different values for a and b and verify that it works as advertised:
(define (test a b)
(let* ((ans (extended-gcd a b))
(x (car ans))
(y (cdr ans)))
(= (gcd a b) (+ (* a x) (* b y)))))
(test 384 256)
=> #t
Notice that the algorithm calculated other values, by changing what you return you can also obtain the following:
Bézout coefficients: old_s, old_t
Greatest common divisor: old_r
Quotients by the gcd: t, s

Define the binary exponential operator CARAT in Lambda Calculus

I am trying to define binary exponential operator in lambda calculus say operator CARAT. For example, this operator may take two arguments, the lambda encoding of number 2 and the lambda encoding of number 4, and computes the lambda encoding of number 16. I don't my answer is right or wrong but It took a day for me to do so. I have used church numerals definition.
Here is my answer. Please correct me if my answer is wrong. I don't how to do it exactly in a right way. If someone knows then please help me to figure out short answer.
A successor function, next, which adds one, can define the natural numbers in terms of zero and next:
1 = (next 0)
2 = (next 1)
= (next (next 0))
3 = (next 2)
= (next (next (next 0)))
From the above conclusion, we can define the function next as follows:
next = λ n. λ f. λ x.(f ((n f) x))
one = (next zero)
=> (λ n. λ f. λ x.(f ((n f) x)) zero)
=> λ f. λ x.(f ((zero f) x))
=> λ f. λ x.(f ((λ g. λ y.y f) x)) -----> (* alpha conversion avoids clash *)
=> λ f. λ x.(f (λ y.y x))
=> λ f. λ x.(f x)
Thus, we can safely prove that….
zero = λ f. λ x.x
one = λ f. λ x.(f x)
two = λ f. λ x.(f (f x))
three = λ f. λ x.(f (f (f x)))
four = λ f. λ x.(f (f (f (f x))))
:
:
:
Sixteen = λ f. λ x.(f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f x))))))))))))))))
Addition is just an iteration of successor. We are now in a position to define addition in terms of next:
m next n => λx.(nextm x) n => nextm n => m+n
add = λ m. λ n. λ f. λ x.((((m next) n) f) x)
four = ((add two) two)
=> ((λ m. λ n. λ f. λ x.((((m next) n) f) x) two) two)
=> (λ n. λ f. λ x.((((two next) n) f) x)two)
=> λ f. λ x.((((two next) two) f x)
=> λ f. λ x.(((( λ g. λ y.(g (g y)) next) two) f x)
=> λ f. λ x.((( λ y.(next (next y)) two) f) x)
=> λ f. λ x.(((next (next two)) f) x)
=> λ f. λ x.(((next (λ n. λ f. λ x.(f ((n f) x)) two)) f) x)
After substituting values for ‘next’ and subsequently ‘two’, we can further reduce the above form to
=> λ f. λ x.(f (f (f (f x))))
i.e. four.
Similarly, Multiplication is an iteration of addition. Thus, Multiplication is defined as follows:
mul = λ m. λ n. λ x.(m (add n) x)
six = ((mul two) three)
=> ((λ m. λ n. λ x.(m (add n) x) two) three)
=> (λ n. λ x.(two (add n) x) three)
=> λ x.(two (add three) x
=> ( λf. λx.(f(fx)) add three)
=>( λx.(add(add x)) three)
=> (add(add 3))
=> ( λ m. λ n. λ f. λ x.((((m next) n) f) x)add three)
=> ( λ n. λ f. λ x.((( three next)n)f)x)add)
=> ( λ f. λ x.((three next)add)f)x)
After substituting values for ‘three’, ‘next’ and subsequently ‘add’ and then again for ‘next’, the above form will reduce to
=> λ f. λ x.(f (f (f (f (f (f x))))))
i.e. six.
Finally, exponentiation can be defined by iterated multiplication
Assume exponentiation function to be called CARAT
CARAT = λm.λn.(m (mul n) )
sixteen => ((CARAT four) two)
=> (λ m. λ n.(m (mul n) four) two)
=> (λ n.(two (mul n)four
=> (two (mul four))
=> ((λ f. λ x.(f (f x))))mul)four)
=> (λ x. (mul(mul x))four)
=> (mul(mul four))))
=> (((((λ m. λ n. λ x.(m (add n) x)mul)four)
=> ((((λ n. λ x.(mul(add n) x)four)
=> (λ x.(mul(add four) x))
=> (λ x (λ m. λ n. λ x.(m (add n) x add)four) x
=> (λ x (λ n. λ x. (add(add n) x)four)x
=> (λ x (λ x (add (add four) x) x)
=> (λ x (λ x (λ m. λ n. λ f. λ x((((m next) n) f) x)add )four) x) x)
=> (λ x (λ x (λ n. λ f. λ x(((add next)n)f)x)four)x)x)
=> (λ x (λ x (λ f. λ x((add next)four)f)x)x)x)
=> (λ x (λ x (λ f. λ x((λ m. λ n. λ f. λ x((((m next) n) f) x)next)four)f)x)x)x)
=> (λ x (λ x (λ f. λ x((λ n. λ f. λ x.(((next next)n)f)x)four)f)x)x)x)
=> (λ x (λ x (λ f. λ x((λ f. λ x ((next next)four)f)x)f)x)x)x)
=> (λ x (λ x (λ f. λ x((λ f. λ x(((λ n. λ f. λ x.(f ((n f) x))next)four)f)x)f)x)x)x)
Now, reducing the above expression and substituting for ‘next’ and ‘four’ and further reducing, we get the following form
λ f. λ x.(f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f x))))))))))))))))
i.e. sixteen.
First of all, re-write next = λ n. λ f. λ x.(f ((n f) x)) as
next = λ num. λ succ. λ zero. succ (num succ zero)
In lambda-calculus parentheses are used just for grouping; an application is signified by juxtaposition of terms, i.e. just by writing one term next to another, and associates to the left.
How are we to read the above? It's a lambda term. When it is applied to some other lambda term, say NUM, it will reduce to a lambda term λ succ. λ zero. succ (NUM succ zero). This will be the immediate result, a representation of the next number of a given number represented by NUM. We can read it as saying to us, "I don't know how to calculate the successor, or what it means to be a zero, but if both are supplied to me I will produce some result according to them, and according to the lambda-term NUM that was used to create me, by supplying those means of calculation to NUM and then applying its result again to the successor function as given to me".
This of course was assuming that NUM respects same assumptions and operates in consistent ways. In particular, ZERO, when applied to an s and a z, must return z:
ZERO = λ s. λ z. z ; == λ a. λ b. b == ...
Everything else follows from this.

SICP Types and Variables

This is from the MIT 6.001 Online Tutor, it's part of the third problem set.
Question: Indicate the type of each of the following expressions. If you need type variables, use A,B,C, etc., starting with A as the leftmost variable.
(lambda (x y) x) = A,B->A
(lambda (p) (p 3))
(lambda (p x) (p x)) = (A->B), A->B
(lambda (x y comp) (if (comp x y) x y))
As you can see I solved 1 and 3, but that was mainly out of luck. I still am having issues with understanding the concept and that is stopping me from solving 2 and 4.
Lecture slides can be found here (view the last few).
A, B -> A
(number -> A) -> A
(A -> B), A -> B
A, A, (A, A -> boolean) -> A
(the last assumes that x and y are the same types)

Resources