在Haskell中生成具有条件的随机整数列表

时间:2015-03-27 08:15:13

标签: haskell

这里我试图生成一个整数列表,我希望在不满足md<=1的条件下向列表中添加随机数。 我试了好几次但没有运气。

fx :: Int -> Int -> IO [Int]
fx md s = do
  x <- randomRIO (1,min md s)
  if md<=1
     then return [md]
     else return md:(fx (md-x) s)

1 个答案:

答案 0 :(得分:9)

错误发生在最后一行:

else return md:(fx (md-x) s)

fx的结果位于IO monad中,因此您希望执行纯md前置操作。这正是liftM所做的,你的最后一行应该是

else liftM (md :) (fx (md-x) s)

其他小改进:

  • 你真的不需要IO,你只需要在函数中生成随机数。为此,您可以使用MonadRandom类型类(驻留在具有相同名称的包中)。这将使功能更具体,类型安全和灵活。
  • 生成一个随机数是多余的,然后才检查是否需要它 - 比较md <= 1根本不需要x

因此,改进后的版本可能如下所示:

import Control.Monad
import Control.Monad.Random

fx :: (MonadRandom m) => Int -> Int -> m [Int]
fx md s | md <= 1   = return [md]
        | otherwise = do
              x <- getRandomR (1, min md s)
              liftM (md :) (fx (md-x) s)

没有liftM

的替代方案

也许这更容易理解:

fx :: (MonadRandom m) => Int -> Int -> m [Int]
fx md s | md <= 1   = return [md]
        | otherwise = do
              x  <- getRandomR (1, min md s)
              xs <- fx (md-x) s
              return (md : xs)