纯Haskell Lambda微积分中列表的功能

时间:2020-05-24 00:28:14

标签: haskell lambda functor lambda-calculus parametric-polymorphism

我正在尝试使用Haskell在纯lambda演算中实现各种功能。 一切正常

arr[0]

直到{-# LANGUAGE RankNTypes #-} type List a = forall b. (a -> b -> b) -> b -> b empty :: List a empty = const id cons :: a -> List a -> List a cons x xs f y = f x (xs f y) 的{​​{1}}出现。

map

此错误消息的提示:

List

为什么map :: (a -> b) -> List a -> List b map f xs = xs (cons . f) empty 工作而• Couldn't match type ‘List b’ with ‘(b -> b1 -> b1) -> b1 -> b1’ Expected type: b -> ((b -> b1 -> b1) -> b1 -> b1) -> (b -> b1 -> b1) -> b1 -> b1 Actual type: b -> List b -> List b • In the first argument of ‘(.)’, namely ‘cons’ In the first argument of ‘xs’, namely ‘(cons . f)’ In the expression: xs (cons . f) empty • Relevant bindings include f :: a -> b (bound at Basic.hs:12:5) map :: (a -> b) -> List a -> List b (bound at Basic.hs:12:1) 不工作?既然cons的每个实例都受map约束,那么不是每个List实例都适用吗?

2 个答案:

答案 0 :(得分:3)

Haskell的类型系统功能不足,无法像您那样编写map。改为这样写:

map f xs c n = xs (c . f) n

答案 1 :(得分:2)

问题在于,要使您的地图正常工作,您需要在b类型中选择量化类型变量List aList b(这是“其他” {您使用了{1}},它不是同一类型变量)。为类型变量分配b类型需要阻抗性,GHC不支持。

在这里,我尝试通过使用易爆类型应用程序将forall调用为b来强制实例化xs

xs @(List b) ....

一种可能的解决方案是将map :: forall a b. (a->b) -> List a -> List b map f xs = xs @(List b) (cons . f) empty error: * Illegal polymorphic type: List b GHC doesn't yet support impredicative polymorphism * In the expression: xs @(List b) (cons . f) empty In an equation for `map': map f xs = xs @(List b) (cons . f) empty 包裹在List a中,然后手动执行包裹/展开。

newtype

该代码中散布着newtype L a = L { unL :: List a } map :: forall a b. (a->b) -> List a -> List b map f xs = unL $ xs @(L b) (\y ys -> L (cons (f y) (unL ys))) (L empty) L,但它们是相同的代码。

上面的约瑟夫·西布尔(Joseph Sible)提出了一个更简单的解决方案,它不需要传递多态类型的值。