我试图做一个简单的游戏"使用monads
我扔了六次硬币并计算了数字
我看到的头,然后我掷骰子;
如果骰子上的眼睛数量更多
超过或等于我计算的头数然后我赢了,否则我输了
我声明了以下类型
data Coin = H | T
deriving (Bounded, Eq, Enum, Ord, Show)
data Dice = D1 | D2 | D3 | D4 | D5 | D6
deriving (Bounded, Eq, Enum, Ord, Show)
data Outcome = Win | Lose
deriving (Eq, Ord, Show)
然后我继续定义
class Monad m => MonadGamble m where
toss :: m Coin
roll :: m Dice
在我的脑海中,当调用折腾或滚动时,应提供骰子或硬币值,但它不会
然后我尝试按如下方式编写游戏代码
game = do
i <- 0
x <- [toss, toss, toss, toss, toss, toss]
if x==H
then do
i <- i+1
[]
else []
y <- roll
if y > i
then Win
else Lose
然而它不起作用,因为我在do块中做了一些完全错误的事情,可能是因为我对monads缺乏了解 有人可以在这里提供一些建议吗?
答案 0 :(得分:6)
首先,在Haskell中,您无法分配i = i + 1
之类的变量。在Haskell中,变量始终绑定到单个值。 do
notation中使用的符号<-
始终将变量绑定到monadic操作的结果,并且整个do
块中的monad必须相同。并且do
块中的每个语句都必须是monadic动作,除非它是let
绑定。特别是:
-- isn't allowed because 0 is a number, not something of type 'm X':
i <- 0
-- isn't allowed because a list is not a monadic action:
x <- [toss, toss, toss, toss, toss, toss]
...
i <- i+1 -- can't re-assign a variable
[] -- must be a monadic action, so this must be 'result []'
...
if y > i
then Win -- again must be 'return Win'
...
此外,在if y > i
中,您要将i
与y
类型Dice
进行比较,这是不允许的。相反,我建议您放弃Dice
并让toss
返回一个数字。修正后的版本可能如下所示:
import Control.Monad
data Coin = H | T
deriving (Bounded, Eq, Enum, Ord, Show)
data Outcome = Win | Lose
deriving (Eq, Ord, Show)
class Monad m => MonadGamble m where
toss :: m Coin
roll :: Int -> m Int
game :: (MonadGamble m) => m Outcome
game = do
x <- replicateM 6 toss -- is of type m [Coin]
let i = length (filter (== H) x)
y <- roll 6
if y > i
then return Win
else return Lose
请注意,要运行game
,您需要编写MonadGamble
的实现。