下面的to_c
函数由于类型错误而被拒绝,因为在使用我想用于此处未显示的不相关代码片段的 GADTs 扩展进行编译时。
newtype Church = Church { unC :: forall a. (a -> a) -> a -> a }
to_c :: Int -> Church
to_c 0 = let f0 f c = c in Church f0
to_c n =
let fn f c = iterate f c !! n in Church fn
错误信息:
Couldn't match type ‘a0’ with ‘a’ because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
(a -> a) -> a -> a
Expected type: (a -> a) -> a -> a
Actual type: (a0 -> a0) -> a0 -> a0
In the first argument of ‘Church’, namely ‘fn’
我可以以直接递归的方式重写函数,该函数将进行类型检查并且也可以工作;但是,我很好奇为什么这种迭代方法有缺陷,以及是否可以通过一些巧妙的类型注释来挽救它。