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

时间:2015-07-23 15:37:45

标签: gadt higher-rank-types purescript

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

我的代码如下:

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模式匹配。

这里出了什么问题?

此致

迈克尔

1 个答案:

答案 0 :(得分:5)

在PureScript中不存在用于Haskell中存在类型的语法。您为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)