论弗雷格的丘奇数纲
On Church numeral program under Frege
此程序在 GHC 下正确编译和运行:
type Church a = (a -> a) -> a -> a
ch :: Int -> Church a
ch 0 _ = id
ch n f = f . ch (n-1) f
unch :: Church Int -> Int
unch n = n (+1) 0
suc :: Church a -> Church a
suc n f = f . n f
pre :: Church ((a -> a) -> a) -> Church a
pre n f a = n s z id
where s g h = h (g f)
z = const a
main :: IO ()
main = do let seven = ch 7
eight = suc seven
six = pre seven
print (unch eight)
print (unch six)
但是用弗雷格编译时出现了以下错误:
E /home/xgp/work/flab/src/main/frege/flab/fold.fr:23: type error in expression seven
type is : Int
expected: (t1→t1)→t1
E /home/xgp/work/flab/src/main/frege/flab/fold.fr:23: type error in expression seven
type is : (t1→t1)→t1
expected: Int
E /home/xgp/work/flab/src/main/frege/flab/fold.fr:23: type error in expression seven
type is : (t1→t1)→t1
expected: Int
E /home/xgp/work/flab/src/main/frege/flab/fold.fr:23: type error in
expression seven
type is apparently Int
used as function
为什么?是否可以修改程序在Frege下通过编译?
这是 let 绑定变量类型的泛化确实产生影响的罕见情况之一。
关键是,弗雷格在这方面就像 GHC with pragma -XMonoLocalBinds
,详情请看这里:https://github.com/Frege/frege/wiki/GHC-Language-Options-vs.-Frege#Let-Generalization and here: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/other-type-extensions.html#typing-binds(SPJ 的一篇论文也有 link,这解释了基本原理)
简而言之,这意味着所有未注释的 let bound veriabes 都将具有 monomorphic 类型,并且不能用于不同类型。要恢复多态性,需要显式类型签名。
要让你的程序编译通过,注释 seven
与
的绑定就足够了
seven :: Church a
关于print/println:前者不刷新输出。所以你在 REPL 中有:
frege> print 'a'
IO ()
frege> print 'b'
IO ()
frege> println "dammit!"
abdammit!
IO ()
此程序在 GHC 下正确编译和运行:
type Church a = (a -> a) -> a -> a
ch :: Int -> Church a
ch 0 _ = id
ch n f = f . ch (n-1) f
unch :: Church Int -> Int
unch n = n (+1) 0
suc :: Church a -> Church a
suc n f = f . n f
pre :: Church ((a -> a) -> a) -> Church a
pre n f a = n s z id
where s g h = h (g f)
z = const a
main :: IO ()
main = do let seven = ch 7
eight = suc seven
six = pre seven
print (unch eight)
print (unch six)
但是用弗雷格编译时出现了以下错误:
E /home/xgp/work/flab/src/main/frege/flab/fold.fr:23: type error in expression seven
type is : Int
expected: (t1→t1)→t1
E /home/xgp/work/flab/src/main/frege/flab/fold.fr:23: type error in expression seven
type is : (t1→t1)→t1
expected: Int
E /home/xgp/work/flab/src/main/frege/flab/fold.fr:23: type error in expression seven
type is : (t1→t1)→t1
expected: Int
E /home/xgp/work/flab/src/main/frege/flab/fold.fr:23: type error in
expression seven
type is apparently Int
used as function
为什么?是否可以修改程序在Frege下通过编译?
这是 let 绑定变量类型的泛化确实产生影响的罕见情况之一。
关键是,弗雷格在这方面就像 GHC with pragma -XMonoLocalBinds
,详情请看这里:https://github.com/Frege/frege/wiki/GHC-Language-Options-vs.-Frege#Let-Generalization and here: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/other-type-extensions.html#typing-binds(SPJ 的一篇论文也有 link,这解释了基本原理)
简而言之,这意味着所有未注释的 let bound veriabes 都将具有 monomorphic 类型,并且不能用于不同类型。要恢复多态性,需要显式类型签名。
要让你的程序编译通过,注释 seven
与
seven :: Church a
关于print/println:前者不刷新输出。所以你在 REPL 中有:
frege> print 'a'
IO ()
frege> print 'b'
IO ()
frege> println "dammit!"
abdammit!
IO ()