教会编码转换功能无法使用GADT进行编译

时间:2017-12-30 16:05:57

标签: haskell gadt church-encoding

下面的(varOne, varTwo, varThree).on('click', function(){ // code here }) 函数由于在使用GADTs扩展编译时出现类型错误而被拒绝,我希望将其用于此处未显示的无关代码片段。

to_c

错误讯息:

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

我可以用直接递归样式重写函数,它会键入check并且也可以工作;但是,我很好奇这个迭代方法为什么有缺陷,以及它是否可以用一些聪明的类型注释来挽救。

1 个答案:

答案 0 :(得分:6)

这与GADT没有任何关系,-XGADTs扩展名也暗示-XMonoLocalBinds,这就是真正的问题。它的作用是,因为本地绑定fn没有明确的签名,它想要给它一个不比环境更多态的类型...即在这种情况下根本不是多态的。但是,当然,必须是多态的,所以它实际上可以在Church类型中使用,所以这没有用。

您仍然可以提供显式多态签名:

{-# LANGUAGE RankNTypes, MonoLocalBinds #-}
newtype Church = Church { unC :: forall a. (a -> a) -> a -> a }
to_c :: Int -> Church
-- to_c 0 = ...  -- the base case is redundant.
to_c n =
    let fn :: (a -> a) -> a -> a
        fn f c = iterate f c !! n
    in Church fn

但更简单的解决方案是根本不做任何绑定,然后-XMonoLocalBinds不起作用:

to_c :: Int -> Church
to_c n = Church (\f c -> iterate f c !! n)

...或者,如果您确实进行了绑定,请在Church构造函数中执行此操作,因为环境已经是多态的:

to_c n = Church (let fn f c = iterate f c !! n in fn)