haskell - Haskell 中的变量关联类型/数据类型

标签 haskell polymorphism monad-transformers associated-types

我目前正在尝试重载 MonadTrans 以前的提取函数。我当前的尝试是将内部单子(monad) m 放置为关联类型 Result 的实例:

class ( Monad Result
      , MonadTrans m
      , MonadReader prefix m
      , ) => FooReader prefix m where
  type Result
  runFooReader :: forall b. m b -> prefix -> Result b

instance Monad m => FooReader prefix (ReaderT prefix m)
  type Result = m -- This is there the error is thrown
  runFooReader = runReaderT

Foo 形状有趣的唯一原因是 MonadTransMonadReader 限制。基本上,这会强制所有关联的类型实例成为单态类型(正确吗?)。

然后我想重新设计它,使 Result 成为一个简单的多态变量:

...
class FooReader prefix m where
  runFooReader :: forall b result. m b -> prefix -> result b

...但在实例中,类型 resultw (如果它是 ReaderT 前缀 wm,例如)不会统一。有什么方法可以使这个结果变量/想法具有多态性,但可判定?

最佳答案

清理语法错误并向 Result 添加类型注释,我们得到:

class ( Monad Result
      , MonadTrans m
      , MonadReader prefix m
      ) => FooReader prefix m where
  type Result :: * -> *
  runFooReader :: forall b. m b -> prefix -> Result b

instance Monad m => FooReader prefix (ReaderT prefix m) where
  type Result = m -- Again, error triggered here
  runFooReader = runReaderT

还有一个更有趣的错误:

The RHS of an associated type declaration mentions type variable `m'
  All such variables must be bound on the LHS

这在the GHC docs中进行了扩展:

The visibility of class parameters in the right-hand side of associated family instances depends solely on the parameters of the family. As an example, consider the simple class declaration

class C a b where 
  data T a 

Only one of the two class parameters is a parameter to the data family. Hence, the following instance declaration is invalid:

instance C [c] d where
  data T [c] = MkT (c, d)    -- WRONG!!  'd' is not in scope

Here, the right-hand side of the data instance mentions the type variable d that does not occur in its left-hand side. We cannot admit such data instances as they would compromise type safety.

为了探讨“它会损害类型安全”这一点,想象一下这次 GHCi session :

> :kind! Result
Result :: * -> *
= {- ... well, what? m? -}

您的意思可能是类型结果前缀(ReaderT 前缀 m)= m

仍然存在错误。值得注意的是,m 的种类不一致; MonadTrans 需要一个 (* -> *) -> * -> * 类型的参数,而 MonadReader 的第二个参数需要 * -> *。我不明白你为什么需要 MonadTrans

我不明白你所说的“强制所有关联的类型实例为单态类型”是什么意思;您编写的 Result 类型实际上并不是类型函数,因为它没有任何参数;它的 LHS 上没有任何类型变量。

这是编译的内容:

class ( Monad (Result m)
      , MonadReader prefix m
      ) => FooReader prefix (m :: * -> *) where
  type Result m :: * -> *
  runFooReader :: forall b. m b -> prefix -> Result m b

instance Monad m => FooReader prefix (ReaderT prefix m) where
  type Result (ReaderT prefix m) = m
  runFooReader = runReaderT

 

> :kind! Result (ReaderT Int IO)
Result (ReaderT Int IO) :: * -> *
= IO

关于haskell - Haskell 中的变量关联类型/数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27597160/

相关文章:

haskell - 获取所有可能的邻居坐标

haskell - Haskell 中 FFI 调用的类型自动转换

c++ - “重写”类(class)成员

使用 Haskell/Megaparsec : StateT for building up local, 词法范围进行解析?

scala - 在scalaz中将状态分层

haskell - 在 Haskell 中添加两个复数

haskell - 用否定理解函数组合

c# - 如何在 .NET 7 中使用 System.Text.Json 序列化多级多态类型层次结构?

java - java 难道不应该将重载函数与大多数特定类型相匹配吗?

scala - 为什么我们需要 Scala 中的 Monad Transformers?