For a functional programming excercise I am required to apply primitive recursive functions in haskell. However I do not quite understand yet the definition (and application) of this type of functions.
We are presented the data type Nat to be used, its constructor is:
data Nat = Zero | Succ Nat
To my understanding this means that the type "Nat" can be either a Zero or a Natural Succesor.
Then we have a recursor:
recNat :: a -> (Nat -> a -> a) -> Nat -> a
recNat a _ Zero = a
recNat a h (Succ n) = h n (recNat a h n)
Which I understand is meant to apply recursion to a function?
And I've also been given an example of an addition function using the recursor:
addR :: Nat -> Nat -> Nat
addR m n = recNat n (\ _ y -> Succ y) m
But I don't get how it works, it uses the recNat function with the given two Nats, and also uses an anonymous function as input for recNat ( that is the part I'm not sure what it does! )
So my main issue is what does this do in the function exactly > \ _ y -> Succ y
I'm suppossed to apply this same recursor (RecNat) to apply other operations to Nat, but I'm stuck still trying to understand the example!
You’re right that data Nat = Zero | Succ Nat means that a Nat may be Zero or the Successor of another Nat; this represents natural numbers as a linked list, i.e.:
zero, one, two, three, four, five :: Nat
zero = Zero
one = Succ Zero -- or: Succ zero
two = Succ (Succ Zero) -- Succ one
three = Succ (Succ (Succ Zero)) -- Succ two
four = Succ (Succ (Succ (Succ Zero))) -- Succ three
five = Succ (Succ (Succ (Succ (Succ Zero)))) -- Succ four
-- …
The function of recNat is to fold over a Nat: recNat z k takes a Nat and “counts down” by ones to the final Zero, calling k on every intermediate Succ, and replacing the Zero with z:
recNat z k three
recNat z k (Succ (Succ (Succ Zero)))
-- by second equation of ‘recNat’:
k two (recNat z k two)
k (Succ (Succ Zero)) (recNat z k (Succ (Succ Zero)))
-- by second equation of ‘recNat’:
k two (k one (recNat z k one))
k (Succ (Succ Zero)) (k (Succ Zero) (recNat z k (Succ Zero)))
-- by second equation of ‘recNat’:
k two (k one (k zero (recNat z k zero)))
k (Succ (Succ Zero)) (k (Succ Zero) (k Zero (recNat z k Zero)))
-- by first equation of ‘recNat’:
k two (k one (k zero z))
k (Succ (Succ Zero)) (k (Succ Zero) (k Zero z))
The lambda \ _ y -> Succ y has type a -> Nat -> Nat; it just ignores its first argument and returns the successor of its second argument. Here’s an illustration of how addR works to compute the sum of two Nats:
addR two three
addR (Succ (Succ Zero)) (Succ (Succ (Succ Zero)))
-- by definition of ‘addR’:
recNat three (\ _ y -> Succ y) two
recNat (Succ (Succ (Succ Zero))) (\ _ y -> Succ y) (Succ (Succ Zero))
-- by second equation of ‘recNat’:
(\ _ y -> Succ y) one (recNat three (\ _ y -> Succ y) one)
(\ _ y -> Succ y) (Succ Zero) (recNat (Succ (Succ (Succ Zero))) (\ _ y -> Succ y) (Succ Zero))
-- by application of the lambda:
Succ (recNat three (\ _ y -> Succ y) one)
Succ (recNat (Succ (Succ (Succ Zero))) (\ _ y -> Succ y) (Succ Zero))
-- by second equation of ‘recNat’:
Succ ((\ _ y -> Succ y) zero (recNat three (\ _ y -> Succ y) zero))
Succ ((\ _ y -> Succ y) zero (recNat (Succ (Succ (Succ Zero))) (\ _ y -> Succ y) zero))
-- by application of the lambda:
Succ (Succ (recNat three (\ _ y -> Succ y) zero))
Succ (Succ (recNat (Succ (Succ (Succ Zero))) (\ _ y -> Succ y) zero))
-- by first equation of ‘recNat’:
Succ (Succ three)
Succ (Succ (Succ (Succ (Succ Zero))))
-- by definition of ‘five’:
five
Succ (Succ (Succ (Succ (Succ Zero))))
As you can see, what’s happening here is we’re essentially taking off each Succ from one number and putting it on the end of the other, or equivalently, replacing the Zero in one number with the other number, i.e., the steps go like this:
1+1+0 + 1+1+1+0 2 + 3
1+(1+0 + 1+1+1+0) 1+(1 + 3)
1+1+(0 + 1+1+1+0) 1+1+(0 + 3)
1+1+(1+1+1+0) 1+1+(3)
1+1+1+1+1+0 5
The inner lambda always ignores its first argument with _, so it may be simpler to see how this works with a simpler definition of recNat that literally replaces Zero with a value z and Succ with a function s:
recNat' :: a -> (a -> a) -> Nat -> a
recNat' z _ Zero = z
recNat' z s (Succ n) = s (recNat z s n)
Then addition is slightly simplified:
addR' m n = recNat' n Succ m
This literally says “to compute the sum of m and n, add one m times to n”.
You may find it easier to play around with these numbers if you make a Num instance and Show instance for them:
{-# LANGUAGE InstanceSigs #-} -- for explicitness
instance Num Nat where
fromInteger :: Integer -> Nat
fromInteger n
| n <= 0 = Zero
| otherwise = Succ (fromInteger (n - 1))
(+) :: Nat -> Nat -> Nat
(+) = addR
(*) :: Nat -> Nat -> Nat
(*) = … -- left as an exercise
(-) :: Nat -> Nat -> Nat
(-) = … -- left as an exercise
abs :: Nat -> Nat
abs n = n
signum :: Nat -> Nat
signum Zero = Zero
signum Succ{} = Succ Zero
negate :: Nat -> Nat
negate n = n -- somewhat hackish
instance Show Nat where
show n = show (recNat' (+ 1) 0 n :: Int)
Then you can write 2 + 3 :: Nat and have it display as 5.
Roughly, recNat x f n computes
f (n-1) (f (n-2) (f (n-3) (... (f 0 x))))
So, it applies f to x for n times, each time also passing a "counter" as the first argument of f.
In your case \_ y -> ... ignores the "counter" argument. Hence
addR m n = recNat n (\ _ y -> Succ y) m
can be read as "to compute m+n, apply m times the function Succ to n". This effectively computes ((n+1)+1)+1... where there are m ones in the sum.
You can try to compute the product of two naturals in a similar way. Use \_ y -> ... and express multiplication as repeated addition. You'll need to use the already-defined addR for that.
Additional hint: after multiplication, if you want to compute the predecessor n-1, then the "counter" argument will be very handy, so don't discard that and use \x y -> ... instead. After that, you can derive (truncated) subtraction as repeated predecessor.
Related
I am currently trying to implement primitive recursive factorial in Haskell.
I'm using the function recNat, as a recursor. That is:
recNat :: a -> (Nat -> a -> a) -> Nat -> a
recNat a _ Zero = a
recNat a h (Succ n) = h n (recNat a h n)
This is our attempt, but can't quite figure out what's wrong
factR :: Nat -> Nat
factR Zero = Succ Zero
factR (Succ m) = recNat (Succ m) (\ _ y -> y) (factR m)
I was also trying to implement the exponential function, but it seems even more confusing.
In order to implement a factorial, we can implement a function for multiplication. For the multiplication function, we need the addition function
data Nat = Zero | Succ Nat
add :: Nat -> Nat -> Nat
add a Zero = a
add a (Succ b) = Succ (add a b)
mul :: Nat -> Nat -> Nat
mul a Zero = Zero
mul a (Succ b) = add a (mul a b)
Then the factorial function just comes down to:
fac :: Nat -> Nat
fac Zero = Succ Zero
fac (Succ a) = mul (Succ a) (fac a)
I have written SML code to recursively add two numbers of datatype nat. A function peanify to convert integer to nat. A function decimal to convert nat to integer.
Wanted help with syntax to test fun plus.
Say I want to test for 2 + 1
datatype nat = Zero | Succ of nat
fun peanify (x:int) : nat =
if x=0 then Zero
else Succ (peanify (x-1))
fun decimal (n:nat) : int =
case n of
Zero => 0
| (Succ n) => 1 + (decimal n)
fun plus (x : nat) : (nat -> nat) =
case x of
Zero => (fn y => y)
| Succ x' => (fn y => Succ (plus x' y))
Expected Result-:
val it = Succ (Succ (Succ Zero)) : nat
You can write:
val it = plus (peanify 2) (peanify 1)
I'm learning OCaml in school and recently came came across a program for an assignment that I couldn't understand, and was hoping if somebody could explain it to me. Here's the code:
(* Natural numbers can be defined as follows:
type = ZERO | SUCC of nat;;
For instance, two = SUCC (SUCC ZERO) and three = SUCC (SUCC (SUCC ZERO)).
Write a function 'natadd' that adds two natural numbers in this fashion. *)
# type = ZERO | SUCC of nat;;
# let two = SUCC (SUCC ZERO);;
# let three = SUCC (SUCC (SUCC ZERO));;
# let rec natadd : nat -> nat -> nat =
fun n1 n2 ->
match n1 with
| ZERO -> n2
| SUCC n1 -> SUCC (natadd n1 n2)
;;
Here's a sample output for the code:
# natadd two three;;
- : nat = SUCC (SUCC (SUCC (SUCC (SUCC ZERO))))
What I don't understand is the match-with statement. Does it mean that if n1 is non-zero, then it adds SUCC and uses [SUCC n1] as a new argument in place of n1 for the recursive call?
No, it doesn't use SUCC n1 as the argument of the recursive call, it uses only n1 (the part of the matched SUCC) as the argument. The SUCC is then applied to the result of the recursive call.
The code might be a bit confusing because there are two variables with the name n1. Better might be
let rec natadd : nat -> nat -> nat = fun a b ->
match a with
| ZERO -> b
| SUCC a_pred -> SUCC (natadd a_pred b)
I'm trying to do proofs over dependent functions, and I'm running into a snag.
So let's say we have a theorem f-equal
f-equal : ∀ {A B} {f : A → B} {x y : A} → x ≡ y → f x ≡ f y
f-equal refl = refl
I'm trying to prove a more general notion of equality preservation over dependent functions, and running into a snag. Namely, the type
Π-equal : ∀ {A} {B : A → Set} {f : {a : A} → B a} {x y : A} →
x ≡ y → f x ≡ f y
is making the compiler unhappy, because it can't figure out that f x and f y are of the same type. This seems like it oughta be a fixable issue. Is it?
note; the equivalence relation used is defined like this:
data _≡_ {A : Set}(x : A) : A → Set where
refl : x ≡ x
You can explicitly change the type of f x:
Π-equal : ∀ {α β} {A : Set α} {B : A -> Set β} {f : (x : A) -> B x} {x y : A}
-> (p : x ≡ y) -> P.subst B p (f x) ≡ f y
Π-equal refl = refl
Or
Π-equal'T : ∀ {α β} {A : Set α} {B : A -> Set β} -> ((x : A) -> B x) -> (x y : A) -> x ≡ y -> Set β
Π-equal'T f x y p with f x | f y
...| fx | fy rewrite p = fx ≡ fy
Π-equal' : ∀ {α β} {A : Set α} {B : A -> Set β} {f : (x : A) -> B x} {x y : A}
-> (p : x ≡ y) -> Π-equal'T f x y p
Π-equal' refl = refl
Or you can use heterogeneous equality:
Π-equal'' : ∀ {α β} {A : Set α} {B : A -> Set β} {f : (x : A) -> B x} {x y : A}
-> x ≡ y -> f x ≅ f y
Π-equal'' refl = refl
The subst function also can be useful, here is it's type (C-c C-d P.subst in Emacs):
{a p : .Agda.Primitive.Level} {A : Set a} (P : A → Set p)
{x y : A} →
x ≡ y → P x → P y
Imports used:
open import Relation.Binary.PropositionalEquality as P
open import Relation.Binary.HeterogeneousEquality as H
BTW, your f-equal is cong in the standard library.
It can be handled by heterogeneous equality, which can be imported from Relation.Binary.HeterogeneousEquality:
data _≅_ {ℓ} {A : Set ℓ} (x : A) : {B : Set ℓ} → B → Set ℓ where
refl : x ≅ x
Intuitively, het. equality carries evidence about the equality of the types involved as well as the equality of values.
You can find analogues for functions for standard equality (subst, trans, cong, etc.) in the module. Also, you can convert back and forth standard and het. equality using ≅-to-≡ and ≡-to-≅, but only when the types on the sides are demonstrably equal.
Note that the "rewrite" syntax can't be used with het. equality.
Alternatively, we can use standard equality with one of the sides coerced to the appropriate type:
Π-equal :
∀ {A : Set} {B : A → Set}{f : ∀ a → B a}{x y : A} → (p : x ≡ y) → subst B p (f x) ≡ f y
Π-equal refl = refl
This approach is actually equivalent to het. equality, but I find het. equality much easier to work with.
I'm trying to prove the following:
1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc x} = {!!}
I'm brand new to Adga and don't even really know where to start. Any suggestions or guidance? Obviously very easy to prove on paper but I am unsure of what to tell Agda.
I defined my pow function as follows:
_pow_ : ℕ → ℕ → ℕ
x pow zero = 1
x pow (suc zero) = x
x pow (suc y) = x * (x pow y)
When you pattern match on n in 1-pow and find out it is zero, Agda will take a look at the definition of _pow_ and check if one of the function clauses matches. The first one does, so it will apply that definition and 1 pow zero becomes 1. 1 is obviously equal to 1, so refl will work for the proof.
What about the case when n was suc x? Here's the problem: Agda cannot commit to the second clause (because x could be zero) nor the third clause (because x could be suc y for some y). So you have to go one step further to make sure Agda applies the definition of _pow_:
1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc zero} = {!!}
1-pow {suc (suc x)} = {!!}
Let's check out what is the type of the first hole. Agda tells us it is 1 ≡ 1, so we can use refl again. The last one is a bit trickier, we are supposed to produce something of type 1 * 1 pow (suc x) ≡ 1. Assuming your are using the standard definition of _*_ (i.e. recursion on the left argument and repeated addition on the left side, such as the one in the standard library), this should reduce to 1 pow (suc x) + 0 ≡ 1. Induction hypothesis (that is, 1-pow applied to suc x) tells us that 1 pow (suc x) ≡ 1.
So we are almost there, but we don't know that n + 0 ≡ n (that's because addition is defined by recursion on the left argument, so we can't simplify this expression). One option is to prove this fact, which I leave as an exercise. Here's a hint, though: you might find this function useful.
cong : ∀ {a b} {A : Set a} {B : Set b}
(f : A → B) {x y} → x ≡ y → f x ≡ f y
cong f refl = refl
It's already part of the Relation.Binary.PropositionalEquality module, so you don't need to define it yourself.
So, to recap: we know that n + 0 ≡ n and 1 pow (suc x) ≡ 1 and we need 1 pow (suc x) + 0 ≡ 1. These two facts fit together quite nicely - the equality is transitive, so we should be able to merge 1 pow (suc x) + 0 ≡ 1 pow (suc x) and 1 pow (suc x) ≡ 1 into one proof and indeed, this is the case:
1-pow {suc (suc x)} = trans (+0 (1 pow suc x)) (1-pow {suc x})
And that's it!
Let me mention few other approaches.
The whole proof could also be done using a proof that 1 * x ≡ x, though this is hardly different from what we did before.
You could simplify _pow_ to:
_pow_ : ℕ → ℕ → ℕ
x pow zero = 1
x pow (suc y) = x * (x pow y)
This is slightly more convenient to work with. The proof would be changed accordingly (i.e. it wouldn't have the second clause of the original proof).
And lastly, you could do this:
1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc zero} = refl
1-pow {suc (suc x)} = cong (λ x → x + 0) (1-pow {suc x})
Try to figure out why that works! If you have any problems, let me know in the comments and I'll help you.