Haskell 可以导出 MonadState s
的实例在 T1
低于但不在 T2
然而,这是一个非常相似的类型。我应该以哪种方式修改 T2
的代码?以便 MonadState s
的实例可以自动导出吗?
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Monad.Reader
import Control.Monad.State
newtype T1 r s a =
T1 { runT1 :: ReaderT r (State s) a }
deriving (Monad, MonadReader r, MonadState s)
newtype T2 r s a =
T2 { runT2 :: StateT r (State s) a }
deriving (Monad, MonadState r, MonadState s)
最佳答案
MonadState
的类型不能有两个实例.这是因为 MonadState
定义为
class Monad m => MonadState s m | m -> s where
get :: m s
set :: s -> m ()
state :: (s -> (a, s)) -> m a
关键部分是
| m -> s
.这需要扩展名 FunctionalDependencies
,并声明对于任何 m
,我们自动知道关联的s
.这意味着对于任何给定的 m
, s
只能有一种选择这是有效的。所以你不能让它同时适用于 MonadState r m
和 MonadState s m
除非r ~ s
.如果 r ~ s
,那么编译器如何知道它适用于哪个底层 monad?在这种情况下,我想你也会发现如果你创建 get
代码会更容易理解和使用。和 put
带有后缀的函数,例如 getInner
, setInner
和 getOuter
, setOuter
.
关于haskell - 广义新型推导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25693483/