RankNTypes例如声明?

时间:2010-10-18 07:19:21

标签: haskell types type-systems higher-rank-types

我最近一直在玩RankNTypes并想知道是否可以使用它们 在实例声明中。

这是一个使用open数据类型的简单示例

data (Expr a, Expr b) => Add a b = Add a b deriving(Show)                          

instance (Expr a, Expr b) => Expr (Add a b)

instance (Evaluation a, Evaluation b) => Evaluation (Add a b) where
  eval (Add x y) = eval x + eval y

在这里,我必须编写约束(评估a,评估b),但基本上我只想写一些像(forall a。评估a)。这甚至可能吗?

此致 raichoo

1 个答案:

答案 0 :(得分:4)

(forall a . Evaluation a)没有意义:这意味着每一种类型(包括某人可能制作的任何未来类型)都是Evaluation的实例。

此外,在这种情况下,我认为您列出所需Evaluation实例的代码是正确的做法;不要求超过你实际需要的。

但是有些情况下,能够根据您描述的方向量化类别约束会很好,而且不可能直接。一个示例是您可能希望从MonadPlus自动生成Monoid个实例(使用包装类型来避免OverlappingInstances个问题):

newtype MonoidWrapper m a = MonoidWrapper { unMonoidWrapper :: m a }

instance Monad m => Monad (MonoidWrapper m) where ...

instance (Monad m, forall a . Monoid (m a)) => MonadPlus (MonoidWrapper m) where
    mzero = MonoidWrapper mempty
    mplus (MonoidWrapper a) (MonoidWrapper b) = MonoidWrapper (mappend a b)

你不能写这个,但是使用GADT或存在类型你可以模拟它,但有一些语法上的痛苦:

data MonoidDict a where
    MonoidDict :: Monoid a => MonoidDict a

class AlwaysMonoid m where
    alwaysMonoidDict :: MonoidDict (m a) -- note the implicit forall a here

instance Monad m => Monad (MonoidWrapper m)

instance (Monad m, AlwaysMonoid m) => MonadPlus (MonoidWrapper m) where
    mzero = mymzero
     where
       -- needed to give name to 'a' for ScopedTypeVariables
      mymzero :: forall a . MonoidWrapper m a
      mymzero = case (alwaysMonoidDict :: MonoidDict (m a)) of
                  MonoidDict -> MonoidWrapper mempty
    mplus = mymplus
     where
      mymplus :: forall a . MonoidWrapper m a
              -> MonoidWrapper m a -> MonoidWrapper m a
      mymplus (MonoidWrapper a) (MonoidWrapper b)
         = case (alwaysMonoidDict :: MonoidDict (m a)) of
            MonoidDict -> MonoidWrapper (mappend a b)