如何使用monad随机播放列表?

时间:2018-08-11 07:50:12

标签: haskell

我有以下数据类型:

data Card = Card One | Card Two | ...
data Deck = Deck [Card]

我想在卡组中洗牌机

这是我到目前为止的位置:

import System.Random

shuffle :: Deck -> Deck
shuffle (Deck c) = Deck $ shuffleOnce randomN c
    where   randomN = randomIO >>= (\x -> return (x `mod` 52))
            shuffleOnce n c = (findNth n c : deleteNth n c)
            findNth 0 (x:_) = x
            findNth n (_:xs) = findNth (n-1) xs
            deleteNth 0 (_:xs) = xs
            deleteNth n (x:xs) = x : (deleteNth (n-1) xs)

问题(显然)在这里:

        where   randomN = randomIO >>= (\x -> return (x `mod` 52))

我不知道如何使用IO单子生成随机数。在单调的情况下将随机数从`换为52后,如何将其取出?

或者更好的问题,我实际上是如何洗牌?

请帮助。完整代码here

1 个答案:

答案 0 :(得分:2)

编译器说,问题出在centralManagerDidUpdateState中。 (randomN 1)函数用一个参数调用,但是不接受。

然后就无法确定是哪种类型的随机数,因此我们需要在此处提供一个:

randomN

然后收到randomIO >>= (\x -> return (x `mod` 52)) :: IO Int 错误,这实际上意味着应该No instance for (Eq (IO Int)),但是提供了Int。为了方便起见,我们可以交换IO Int的参数,并将此函数称为:

shuffleOnce n c

之后,错误提示:

shuffleOnce c <$> randomN

我们需要再次使用Expected type: [Card] Actual type: IO [Card] 而不是<$>,只是为了获得“内部” $

IO

因此,我们收到:

Deck <$> shuffleOnce c <$> randomN

我们对此无能为力,但可以更改Couldn't match expected type ‘Deck’ with actual type ‘IO Deck’ 函数的类型:

shuffle

然后我们意识到,shuffle :: Deck -> IO Deck shuffle (Deck c) = Deck <$> shuffleOnce c <$> randomN where randomN = randomIO >>= (\x -> return (x `mod` 52)) :: IO Int shuffleOnce c n = (findNth n c : deleteNth n c) findNth 0 (x:_) = x findNth n (_:xs) = findNth (n-1) xs deleteNth 0 (_:xs) = xs deleteNth n (x:xs) = x : (deleteNth (n-1) xs) 是一个具有副作用的函数,因为它包含随机数,这些随机数是“从外部世界接收的”。实际上,在类型定义中包含此信息似乎合乎逻辑。