【问题标题】:RankNTypes for instance declarations?RankNTypes 用于实例声明?
【发布时间】:2011-04-24 06:13:17
【问题描述】:

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

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

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

在这里我必须写出像(Evaluation a, Evaluation b)这样的约束,但基本上我只想写像(forall a.Evaluation a)这样的东西。这甚至可能吗?

问候, 雷乔

【问题讨论】:

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


    【解决方案1】:

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

    另外,在这种情况下,我认为列出您想要的 Evaluation 实例的代码是正确的做法;不要要求比你实际需要的更多。

    但在某些情况下,如果能够按照您描述的方式对类约束进行量化会很好,但这是不可能直接进行的。一个示例是,您可能希望从 Monoid 自动创建 MonadPlus 实例(使用包装器类型来避免 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)
    

    【讨论】:

    • 谢谢,我会玩一下这个:)
    猜你喜欢
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 2012-03-10
    • 2012-11-28
    • 1970-01-01
    • 2019-09-18
    • 2012-01-17
    • 1970-01-01
    相关资源
    最近更新 更多