I have been trying to implement church numerals in F#. They were briefly introduced in a course at college and I may have gone down the rabbit hole a bit since then. I have working Predecessor, Successor, Add and Operations but I can't get subtract to work. I'm trying to implement subtract b applying predecessor multiple times. What I find peculiar is that the penultimate line in my code works but what I assume is equivalent, the last line, does not work. There is a type mismatch.
I'm very new to F# so any help would be appreciated. Thank you.
//Operations on tuples
let fst (a,b) = a
let snd (a,b) = b
let pair a b = (a,b)
//Some church numerals
let c0 (f:('a -> 'a)) = id
let c1 (f:('a -> 'a)) = f
let c2 f = f << f
let c3 f = f << f << f
let c4 f = f << f << f << f
// Successor and predecessor
let cSucc (b,(cn:('a->'a)->('a->'a))) = if b then (b, fun f -> f << (cn f)) else (true, fun f -> (cn f))
let cPred (cn:('a->'a)->('a->'a)) = fun f -> snd (cn cSucc (false, c0)) f
//let cSucc2 cn = fun f -> f << (cn f)
// Add, Multiply and Subtract church numerals
let cAdd cn cm = fun f -> cn f << cm f
let cMult cn cm = cn >> cm
let cSub cn cm = cm cPred cn
//Basic function for checking validity of numeral operations
let f = (fun x -> x + 1)
//This works
(cPred << cPred) c3 f 0
//This doesn't
c2 cPred c3 f 0
This is the type mismatch error given (Intellisense says this is an error with cPred on the last line of the code). I can see the output type is inferred wrong. Is there a way to fix it or is there something fundamentally wrong with how I have written this implementation?
'((bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> (bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)'
but given a
'((bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> ('a -> 'a) -> 'a -> 'a'
The types ''a' and 'bool * (('a -> 'a) -> 'a -> 'a)' cannot be unified.
– MHilton Jan 17 '18 at 15:43