国家monad组成的麻烦

时间:2012-09-20 15:36:07

标签: haskell state monads composition

我正在尝试http://www.haskell.org/haskellwiki/State_Monad#Complete_and_Concrete_Example_1

给出的示例

这使得解决方案的可解决性超出了我的理解范围。这是我尝试过但我得到的编译错误如下:

Couldn't match expected type `GameValue -> StateT GameState Data.Functor.Identity.Identity b0'
            with actual type `State GameState GameValue'
In the second argument of `(>>=)', namely `g2'
In the expression: g1 >>= g2
In an equation for `g3': g3 = g1 >>= g2
Failed, modules loaded: none.

以下是代码:参见结束行

module StateGame where
import Control.Monad.State

type GameValue = Int
type GameState = (Bool, Int)

-- suppose I want to play one game after the other
g1 = playGame "abcaaacbbcabbab"
g2 = playGame "abcaaacbbcabb"
g3 = g1 >>= g2

m2 = print $ evalState g3 startState

playGame :: String -> State GameState GameValue
playGame []     = do
    (_, score) <- get
    return score

playGame (x:xs) = do
    (on, score) <- get
    case x of
         'a' | on -> put (on, score + 1)
         'b' | on -> put (on, score - 1)
         'c'      -> put (not on, score)
         _        -> put (on, score)
    playGame xs

startState = (False, 0)

main str = print $ evalState (playGame str) startState

2 个答案:

答案 0 :(得分:2)

g1 = playGame "abcaaacbbcabbab"
g2 = playGame "abcaaacbbcabb"
g3 = g1 >>= g2

g1g2都属于State GameState GameValue类型。但(>>=)的类型为

(>>=) :: Monad m => m a -> (a -> m b) -> m b

因此它的第二个参数必须是一个函数。如果第一个参数是g1,则该函数必须具有类型

GameValue -> State GameState b

这是错误消息中的“预期类型”。但g2有不同的类型,即“实际类型”。

g3定义中您想要的组合子是(>>) :: Monad m => m a -> m b -> m b

g3 = g1 >> g2

答案 1 :(得分:2)

您可以通过两种方式组合两款游戏。第一种选择是在第一场比赛之后运行第二场比赛,从一个新的状态开始。您可以使用以下方式执行此操作:

main = do
    print $ evalState g1 startState
    print $ evalState g2 startState

或者,您可以在第一场比赛结束时进行第二场比赛。您可以使用以下方式执行此操作:

g3 = do
    g1
    g2

...这只是语法糖:

g3 = g1 >> g2

...并运行:

main = print $ evalState g3 startState