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

Aks*_*ari 5 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)
Run Code Online (Sandbox Code Playgroud)

Pet*_*lák 9

错误发生在最后一行:

else return md:(fx (md-x) s)
Run Code Online (Sandbox Code Playgroud)

结果fx是在IOmonad中,并且结果你想要执行一个前置的纯操作md.这正是liftM你的最后一行应该是什么

else liftM (md :) (fx (md-x) s)
Run Code Online (Sandbox Code Playgroud)

其他小改进:

  • 你真的不需要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)
Run Code Online (Sandbox Code Playgroud)

替代没有 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)
Run Code Online (Sandbox Code Playgroud)