I’m trying to define some basic Primitive Recursive functions in Haskell. Why is my times function recursing one too many times (ie eval times[x,y] is resulting in (x+1)*y)? I think my problem is generally due to a poor understanding of how the Composition function works. Please don’t give an answer without an explanation to clarify my understanding.
import Prelude hiding (pred,and,or,not)
data PR = Z
| S
| P Int
| C PR [PR]
| PR PR PR
deriving Show
eval :: PR -> [Integer] - Integer
eval Z _ = 0
eval S [x] = x+1
eval (P n) xs = nth n xs
eval (C f gs) xs = eval f (map (\g -> eval g xs) gs)
eval (PR g h) (0:xs) = eval g xs
eval (PR g h) (x:xs) = eval h ((x-1) : eval (PR g h) ((x-1):xs) : xs)
nth _ [] = error "nth nil"
nth 0 _ = error "nth index"
nth 1 (x:_) = x
nth (n) (_:xs) = nth (n-1) xs
one = C S [Z]
plus = PR (P 1) (C S [P 2])
times = PR (P 1) (C plus [P 2, P 3])
I’ve tried a few other things for times the closest being times = PR (P 1) (C plus[P 2, P 2] but this comes out to 2x*y I thought “Well I’ll just replace one of those P 2‘s with Z and then it will be x*y” This actually makes it the identity function of y and I have no idea why.
This definition for times seems to work:
This makes sense since 0*x = 0 not 1.
Note that I had to change the definition of
eval (C ...)in order for it to compile:More detailed explanation…
We know that
timeswill be of the formPR Z hfor someh.Let’s expand
eval (PR Z h) (x+1:y:ys)…because by induction we know
eval (PR z h) (x:y:ys) = x*y.So what does
hhave to be in order to get(x+1)*y = y+x*y? We need to addy(which isP 3) andx*y(which isP 2), so we should definehas:If you use
P 1instead ofZ, then your base case isyand not0:The recursion stays the same, so you’re off by
yin your answer.