我正在尝试使用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)
Run Code Online (Sandbox Code Playgroud)
然后我继续定义
class Monad m => MonadGamble m where
toss :: m Coin
roll :: m Dice
Run Code Online (Sandbox Code Playgroud)
在我的脑海中,当调用折腾或滚动时,应提供骰子或硬币值,但事实并非如此
然后我尝试按如下方式编写游戏代码
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
Run Code Online (Sandbox Code Playgroud)
然而它不起作用,因为我在do块中做了一些完全错误的事情,可能是因为我对monad缺乏了解可以有人在这里提供一些建议吗?
首先,在Haskell中你不能分配像i = i + 1.在Haskell中,变量始终绑定到单个值.符号中<-使用的do符号总是将变量绑定到monadic动作的结果,并且monad在整个do块中必须相同.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'
...
Run Code Online (Sandbox Code Playgroud)
此外,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
Run Code Online (Sandbox Code Playgroud)
请注意,为了运行,game您需要编写一个实现MonadGamble.