我目前正在尝试重载 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
形状有趣的唯一原因是 MonadTrans
和 MonadReader
限制。基本上,这会强制所有关联的类型实例成为单态类型(正确吗?)。
然后我想重新设计它,使 Result
成为一个简单的多态变量:
...
class FooReader prefix m where
runFooReader :: forall b result. m b -> prefix -> result b
...但在实例中,类型 result
和 w
(如果它是 ReaderT 前缀 w
为 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) 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/