Class Haskell:使用monad类

Class Haskell:使用monad类,class,haskell,monads,Class,Haskell,Monads,作为一项任务,我需要与哈斯凯尔的蒙纳德合作,创建一个赌博游戏,它有一个简单的规则:掷6枚硬币,数人头,掷骰子,如果结果等于或大于你赢的人头数,否则你输。我得到了以下定义赌博单子的“框架”: 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 Ou

作为一项任务,我需要与哈斯凯尔的蒙纳德合作,创建一个赌博游戏,它有一个简单的规则:掷6枚硬币,数人头,掷骰子,如果结果等于或大于你赢的人头数,否则你输。我得到了以下定义赌博单子的“框架”:

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 :: MonadGamble m => m Outcome
game = undefined
然而,我对单子还是新手,我不知道如何与他们合作。例如:游戏定义应该实现我上面解释的游戏,但是我应该如何使用这个赌博单子,例如,执行一个或多个掷骰/掷骰,并获得结果值,以便我可以使用/使用它们

根据我的理解,Monad上总是有两个默认函数:return和(>>=),但我不知道这将如何应用于MonadGable Monad

如果有人能在这方面帮助我,我将不胜感激

致以最良好的祝愿,
Skyfe.

首先,
MonadGamble
在技术上不是monad,而是一个扩展monad的类型类,因此它有两个相关联的东西:
toss
roll
,分别表示toss或roll的值。在
game
的类型签名中,
m
是monad,它是
MonadGamble
的一个实例,因此我们可以自动使用
toss
roll

这里可以使用Haskell的do符号。因为我不想做整个作业,所以我不会详细介绍,但下面是如何编写一个单子,测试两次投币是否相同:

twoFlips :: MonadGamble m => m Bool
twoFlips = do
    coin1 <- toss
    coin2 <- toss
    return (coin1 == coin2)

您可以将
MonadGamble
视为一种小型语言,具有四种结构:

do
    x <- a
    b
这是一个简单的程序,只返回
x

toss
这是一个简单的程序,掷硬币一次并返回结果(正面或反面),然后

这是一个简单的程序,可以滚动模具一次并返回结果(六个面之一
D1
-
D6

注意
Monad
结构
do
return
也是
MonadGamble
语言的结构;这就是
Monad m=>
MonadGamble
声明中的意思

您需要做的是编写一个程序来实现所描述的游戏,使用上面定义的四个“构造”。既然你是单子的新手,你可能想用这四种结构写游戏,考虑如何通过编写你自己的助手函数来简化它,然后看看它给你的助手函数提供了什么名字(我怀疑你需要任何它没有的东西)。 为了让您开始,这里有一个程序可以滚动模具,然后根据结果掷硬币一次或两次:

-- | Roll the die, then if the result is 1-3 flip the coin once, otherwise twice,
-- returning a list of the results.
roller = do
    d <- roll
    if d `elem` [ D1, D2, D3 ]
        then do
            c <- flip
            return [ c ]
        else do
            c0 <- flip
            c1 <- flip
            return [ c0, c1 ]
——|掷骰子,如果结果是1-3,则掷硬币一次,否则两次,
--返回结果列表。
滚筒=do

d您可以编写游戏的整个逻辑,而无需实现
MonadGamble
,然后您可以编写
实例MonadGamble一些现有的\u monad,其中…
,以获得它运行的实际行为。需要明确的是:在Haskell中,“类型”是(大致)一组值。“类”是一组类型(而不是一组值)。因此,
MonadGamble
是一组类型,每个类型都有
>=
返回
操作,加上
MonadGamble
操作
toss
roll
。谢谢!我想我应该使用Haskell的结构,它实际上就是

toss
roll
-- | Roll the die, then if the result is 1-3 flip the coin once, otherwise twice,
-- returning a list of the results.
roller = do
    d <- roll
    if d `elem` [ D1, D2, D3 ]
        then do
            c <- flip
            return [ c ]
        else do
            c0 <- flip
            c1 <- flip
            return [ c0, c1 ]