0

我正在尝试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
4

2 回答 2

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

g1并且g2都是 type 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
于 2012-09-20T15:47:03.823 回答
2

有两种方法可以组合您的两个游戏。第一种选择是在第一场比赛之后运行第二场比赛,从一个新鲜的状态开始。你这样做使用:

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

或者,您可以让第二场比赛从第一场比赛结束的地方开始。你这样做使用:

g3 = do
    g1
    g2

...这只是语法糖:

g3 = g1 >> g2

...并运行它:

main = print $ evalState g3 startState
于 2012-09-20T15:51:02.573 回答