数据构造器中的 Rank-2 类型

Rank-2 types in data constructors

我一直在尝试使用 rank-2 类型在 PureScript 中编码 GADT,如 here 对 Haskell

所述

我的代码如下:

data Z
data S n

data List a n 
  = Nil (Z -> n)
  | Cons forall m. a (List a m) (S m -> n)

fw :: forall f a. (Functor f) => (forall b . (a -> b) -> f b) -> f a
fw f = f id

bw :: forall f a. (Functor f) => f a -> (forall b . (a -> b) -> f b)
bw x f = map f x

nil :: forall a. List a Z
nil = fw Nil

cons :: forall a n. a -> List a (S n)
cons a as = fw (Cons a as)


instance listFunctor :: Functor (List a) where
    map f (Nil k) = Nil (f <<< k)
    map f (Cons x xs k) = Cons x xs (f <<< k)

编译器抱怨 Wrong number of arguments to constructor Main.Cons,指的是 Functor 实例中的 LHS 模式匹配。

这里出了什么问题?

此致,

迈克尔

Haskell 中用于存在类型的语法在 PureScript 中不存在。您为 Cons 编写的是具有单个通用量化参数的数据构造函数。

您可能想尝试使用 purescript-exists 来编码存在类型。

另一种选择是使用 GADT 的最终无标签编码:

class Listy l where
  nil :: forall a. l Z a
  cons :: forall a n. a -> l n a -> l (S n) a

您可以为任何有效的 Listy 实例编写条款:

myList :: forall l. (Listy l) => l (S (S Z)) Int
myList = cons 1 (cons 2 nil)

并通过编写实例来解释它们

newtype Length n a = Length Int

instance lengthListy :: Listy Length where
  nil = Length 0
  cons _ (Length n) = Length (n + 1)

newtype AsList n a = AsList (List a)

instance asListListy :: Listy AsList where
  nil = AsList Nil
  cons x (AsList xs) = AsList (Cons x xs)