haskell - 实例声明的RankNTypes?

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

我最近一直在玩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

在这里,我必须编写类似(评估a,评估b)的约束,但是基本上我只想写类似(总a。评估a)的约束。这有可能吗?

问候,
雷乔

最佳答案

(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)

关于haskell - 实例声明的RankNTypes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3957192/

相关文章:

java - 对象类型和引用类型之间真的很困惑

haskell - 在 GHCI 中时正确的行为,在文件中时键入错误

haskell - 在 VS Code 中调试 haskell

android - 有什么方法可以检查设备是否支持手写笔输入?

go - 通过 Golang 中的方法更改类型的基础值

kotlin - 类型是什么意思!在 Kotlin ?

haskell - 我如何解释这篇论文上的打字规则?

typescript - `any[never]` 是 `any` 类型是否正确?

haskell - 使用 Amazonka 和 Servant 从 S3 存储桶流式传输

haskell - 使用 Haskell 工具堆栈初始化新的 GHCJS 项目