Haskell 广义新类型导出
Haskell可以在下面的Haskell 广义新类型导出,haskell,monads,state-monad,deriving,newtype,Haskell,Monads,State Monad,Deriving,Newtype,Haskell可以在下面的T1中派生出MonadState s的实例,但在T2中却不能派生出该实例,但这是一种非常类似的类型。我应该以何种方式修改T2的代码,以便可以自动派生MonadState s的实例 {-# LANGUAGE GeneralizedNewtypeDeriving #-} import Control.Monad.Reader import Control.Monad.State newtype T1 r s a = T1 { runT1 :: ReaderT r
T1
中派生出MonadState s
的实例,但在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
。这需要扩展名功能相关性
,并说明对于任何m
,我们都会自动知道相关的s
。这意味着对于任何给定的m
,对于s
只能有一个有效的选项。因此,除非r~s
,否则不能让它同时适用于MonadState rm
和MonadState sm
。如果r~s
,那么编译器如何知道应用它的底层monad?在这种情况下,我想您还会发现,如果您创建get
和put
函数,这些函数都有后缀来指示哪些函数,比如getInner
,setInner
和getOuter
,setOuter
,那么理解和使用代码就会容易得多