Haskell/解决方案/理解 Monad
外观
这些解决方案适用于Haskell/理解 Monad的旧版本。有些练习在书中被省略,其他的被合并到其他章节。 |
练习 |
---|
|
2. 使用章节中定义的randomNext
、Seed
和rollDie
rollNDice :: Int -> Seed -> ([Int], Seed) rollNDice 0 seed = ([], seed) rollNDice n seed = let (die, seed0) = rollDie seed (rest, seed1) = rollNDice (n-1) seed0 in ((die : rest) , seed1)
该函数获得第一个骰子和种子,然后递归调用自身以掷出 N 个骰子,一旦RollNDice
到达基本情况,它就会反过来构建一个骰子列表。然后,该函数返回骰子列表和传递给基本情况的最终种子rollNDice 0 seed = ([], seed)
。
3. 我们使用 mkStdGen 获取计算机的随机数生成器,并为它提供一个任意数字 232。首先,在文件开头使用import System.Random
type Seed = StdGen
rollDie1 :: Seed -> (Int, Seed) rollDie1 seed = randomR (1,6) seed
在 Prelude 中
Main> rollDie1 (mkStdGen 232) (3,1017593109 40692)
练习 |
---|
|
1. 您之前已经见过(>>==)
定义下面的所有内容。因此,直到那一点的所有内容都只是为了设置一切。我将>>=
命名为>>==
,将return
命名为return1
,因为本章专门使用bind
和return
来处理随机数;而真正的bind
和return
更加通用,因此出于某些原因无法使用 -----------------> 在那里。至少它有效;您还想从我这里得到什么?鲜血?
在文件开头使用import System.Random
type Seed = StdGen type Random1 a = Seed -> (a, Seed) rollDie :: Random1 Int rollDie seed = randomR (1,6) seed (>>==) :: Random1 a -> (a -> Random1 b) -> Random1 b (>>==) m g = \seed0 -> let (result1, seed1) = m seed0 (result2, seed2) = (g result1) seed1 in (result2, seed2) return1 :: a -> Random1 a return1 x = \seed0 -> (x, seed0) rollNDice1 :: Int -> Random1 [Int] rollNDice1 0 = return1 [] rollNDice1 n = rollDie >>== (\d1 -> rollNDice1 (n-1) >>== (\rest -> return1 (d1 : rest)))
在 prelude 中
*Main> rollNDice1 20 (mkStdGen 231) ([4,3,1,1,2,3,5,4,2,5,6,4,6,2,4,5,6,5,1,5],1927676552 238604751)
如果您想知道:您将(mkStdGen 232111)
传递给rollNDice1
,因为rollNDice 20
本身只会创建一个Random1 [Int]
;您需要将新形成的Random1 [Int]
传递一个种子,以(mkStdGen 242)
的形式,才能让它开始输出随机数。
练习 |
---|
|
1.
putString :: String -> IO () putString [] = putChar '\n' putString (s:xs) = putChar s >> putString xs
练习 |
---|
修正(>>=) 的定义,以考虑State 构造函数。您需要使用模式匹配来删除State 构造函数。 |
(State a) >>= f = State $ \s -> let (a',s') = a s (State b) = f a' in b s'
练习 |
---|
|
a >>= f = State $ \s -> let (a',s') = runState a s in runState (f a') s'