RankNTypes例如声明?

rai*_*hoo 5 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
Run Code Online (Sandbox Code Playgroud)

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

问候,raichoo

GS *_*ica 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)
Run Code Online (Sandbox Code Playgroud)

你不能写这个,但使用 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)
Run Code Online (Sandbox Code Playgroud)