0

使用 mtl,派生 MonadState 似乎可以正确提升状态操作:


:set -XGeneralizedNewtypeDeriving
import Control.Applicative (Applicative)
import Control.Monad.Trans ( MonadIO, liftIO )
import Control.Monad.State (MonadState, evalStateT, modify, StateT, gets)

data State = State { int:: Int }
newtype St a = St { unSt :: StateT State IO a } deriving (Functor, Applicative, Monad, MonadIO, MonadState State)

let testLift = gets int >> return () :: St ()

对于变压器,没有 MonadState


:set -XGeneralizedNewtypeDeriving
import Control.Monad.Trans.State.Strict (runStateT, evalStateT, modify, StateT, gets)
import Control.Monad.IO.Class ( MonadIO, liftIO )
import Control.Applicative (Applicative)


data State = State { int:: Int }
newtype St a = St { unSt :: StateT State IO a } deriving (Functor, Applicative, Monad, MonadIO)


let testLift = gets int >> return () :: St ()
Couldn't match type `StateT State m0' with `St'
Expected type: St Int
  Actual type: StateT State m0 Int
In the return type of a call of `gets'
In the first argument of `(>>)', namely `gets int'
In the expression: gets int >> return () :: St ()

我应该怎么做才能使用变压器来完成这项工作?

4

2 回答 2

6

你应该用它mtl来完成这项工作。mtl并且transformers不是真正的竞争对手——mtl 取决于变压器!存在添加类似使用功能依赖项的类MonadState,因此它们不必成为核心(Haskell-98)类型定义的一部分。还有一个包 ( monads-tf) 改为使用类型族,它也兼容transformers(但实际上,你不应该使用它)。

也许我应该问:你为什么“从 mtl 切换到变压器”?

于 2013-07-14T20:54:04.387 回答
1

MonadState实例位于 packagemonads-tfmonads-fd中,具体取决于您使用的是类型函数还是函数依赖。我试过了monads-tf(因为那是我更喜欢的包),GHC 无法派生 的MonadState实例St,所以你必须自己写一个。

{-# OPTIONS_GHC -package transformers -package monads-tf -hide-package mtl #-}
{-# LANGUAGE GeneralizedNewtypeDeriving, TypeFamilies #-}

import Control.Monad.Trans.State.Strict (runStateT, evalStateT, modify, StateT)
import Control.Monad.State.Class  -- MonadState class
import Control.Monad.IO.Class ( MonadIO, liftIO )
import Control.Applicative (Applicative)

data State = State { int:: Int }
newtype St a = St { unSt :: StateT State IO a } deriving (Functor, Applicative, Monad, MonadIO)

instance MonadState St where
  type StateType St = State
  get = St get
  put x = St (put x)
于 2013-07-14T18:40:47.187 回答