我正在尝试使用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
实例都适用吗?
答案 0 :(得分:3)
Haskell的类型系统功能不足,无法像您那样编写map
。改为这样写:
map f xs c n = xs (c . f) n
答案 1 :(得分:2)
问题在于,要使您的地图正常工作,您需要在b
类型中选择量化类型变量List a
为List 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)提出了一个更简单的解决方案,它不需要传递多态类型的值。