纯 Haskell Lambda 微积分中列表的函子性

Functoriality of List in Pure Haskell Lambda Calculus

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

{-# 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)

直到 map for 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 的每个实例都适用于 b 的每个值,因为它受 forall 约束吗?

Haskell 的类型系统不够强大,无法像您那样编写 map。改为这样写:

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

问题是,要使地图正常工作,您需要将 List a 类型中的量化类型变量 b 选择为 List b(这是 "other"b你用的,不是同类型变量)。将 forall 类型分配给类型变量需要间接性,GHC 不支持。

在这里,我尝试通过使用显式应用程序将 xs 调用为 xs @(List b) .... 来强制实例化 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 中,然后手动执行 wrapping/unwrapping。

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)

代码中充斥着 LunL,但它们是相同的代码。

上面的 Joseph Sible 提出了一个更简单的解决方案,它不需要传递多态类型的值。