F# F中的教会数字#

F# F中的教会数字#,f#,functional-programming,type-inference,lambda-calculus,church-encoding,F#,Functional Programming,Type Inference,Lambda Calculus,Church Encoding,我一直在尝试用F#实现教堂数字。他们在大学的一门课程中被简要介绍过,从那以后我可能有点陷入了困境。我有工作的前导、后继、加法和运算,但我不能让减法工作。我试图多次实现减法b。我觉得奇怪的是,我的代码倒数第二行是有效的,但我假设的是等效的,最后一行是无效的。存在类型不匹配 我对F#很陌生,所以任何帮助都将不胜感激。多谢各位 //Operations on tuples let fst (a,b) = a let snd (a,b) = b let pair a b = (a,b) //Some

我一直在尝试用F#实现教堂数字。他们在大学的一门课程中被简要介绍过,从那以后我可能有点陷入了困境。我有工作的前导、后继、加法和运算,但我不能让减法工作。我试图多次实现减法b。我觉得奇怪的是,我的代码倒数第二行是有效的,但我假设的是等效的,最后一行是无效的。存在类型不匹配

我对F#很陌生,所以任何帮助都将不胜感激。多谢各位

//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

在下面的解释中,我将假设
类型CN'a)->'a->'a
(其中“CN”代表“教堂数字”)的定义,以缩短解释并减少混乱

您尝试将
c2
应用于
cPred
失败,因为
c2
需要类型为
'a->'a
的参数,但
cPred
不是此类函数


您可能希望
cPred
与预期类型匹配,因为您已将其声明为
CN
,但这不是真正的类型。由于您正在将参数
cn
应用于类型
bool*cn
(即
cSucc
的类型),编译器推断
cn
的类型必须为
cn>->cn->bool*cnt谢谢。这很有帮助。我注意到您将Church数字定义为多次应用于参数x的函数。这是一个好主意吗?它没有区别。你可以说
f(fx)
(f
'((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.
let f (g: 'a -> 'a list) = g 1, g "a"
let f g1 g2 = g1 1, g2 "a"
let g x = [x]
f g g
// > it : int list * string list = [1], ["a"]
f (g :: forall a. a -> [a]) = (g 1, g "a")
g x = [x]
f g
==> ([1], ["a"])
type G = 
    abstract apply : 'a -> 'a list

let f (g: G) = g.apply 1, g.apply "a"
let g = { new G with override this.apply x = [x] }
f g
// it : int list * string list = ([1], ["a"])
type CN = 
    abstract ap : ('a -> 'a) -> 'a -> 'a
let c0 = { new CN with override __.ap f x = x }
let c1 = { new CN with override __.ap f x = f x }
let c2 = { new CN with override __.ap f x = f (f x) }
let c3 = { new CN with override __.ap f x = f (f (f x)) }
let c4 = { new CN with override __.ap f x = f (f (f (f x))) }
let cSucc (b,(cn:CN)) = 
    if b 
    then (b, { new CN with override __.ap f x = f (cn.ap f x) }) 
    else (true, cn)

let cPred (cn:CN) = snd (cn.ap cSucc (false, c0))
let cAdd (cn: CN) (cm: CN) = { new CN with override __.ap f x = cn.ap f (cm.ap f x) }
let cMult (cn: CN) (cm: CN) = { new CN with override __.ap f x = cn.ap cm.ap f x }
let cSub (cn: CN) (cm: CN) = cm.ap cPred cn
let f = (fun x -> x + 1)

//This works
((cPred << cPred) c3).ap f 0

//This also works now
(c2.ap cPred c3).ap f 0