
Thanks Stephen, That looks like a nice set of slides. You're right that what I call the mapFn and the reduceFn could be combined into one function. Logically, though, I think it's more intuitive if they are separated. In addition, it seems important to allow for the possibility of having a function at the terminal point. For example, here's how I would define merge. merge xs ys = recursionEngine (\(xs, ys) -> null xs || null ys) (\(xs, ys) -> xs ++ ys) (:) (\(x:xs, y:ys) -> min x y) (\(x:xs, y:ys) -> if x <= y then (xs, y:ys) else (x:xs, ys)) (xs, ys) I'm not sure how to translate that into the genPR formulation. merge xs ys = genPR (\(xs, ys) -> null xs || null ys) (\(x:xs, y:ys) -> if x <= y then (xs, y:ys) else (x:xs, ys)) <There is no constant that goes here.> (\(x:xs, y:ys) merged -> (min x y) : merged) Besides the problem with the third argument, the fourth argument is awkward since it must take both heads, take their min, and then add them to the result of the recursive call. I'd prefer to take the heads and the min in a separate step as in the fourth argument to recursionEngine. *-- Russ * On Sat, Nov 6, 2010 at 2:10 AM, Stephen Tetley wrote:
Hello Russ
Richard Kieburtz has a slightly smaller formulation of primitive recursion on page 13 of these slides - the fold-like argument 'h' doesn't appear to need a change of type:
http://programatica.cs.pdx.edu/P/Programatica%20Logic1.pdf
genPR :: (a -> Bool) -> (a -> a) -> c -> (a -> c -> c) -> a -> c genPR p b g h x = if p x then g else h x (genPR p b g h (b x))
-- factorial function: fact :: Integer -> Integer fact = genPR (==0) (subtract 1) 1 (*)
Ignoring changes in argument order, the type of your recursionEngine is one term and one type variable larger:
recursionEngine :: (a -> Bool) -> (a -> c) -> (b -> c -> c) -> (a -> b) -> (a -> a)-> a -> c
Best wishes
Stephen
participants (1)
-
Russ Abbott