在monadic上下文中生成列表

时间:2015-08-15 07:17:06

标签: list haskell monads

据我了解,您可以使用haskell中的'draw from'(<-)关键字从do-notation中的monadic上下文中取值:

func = do
    x <- getRandom
    let y = (x + 1)
    return y

生成列表时如何应用此功能?假设我正在映射一个函数f :: (MonadRandom m) => Int -> m a,该函数接受一个整数并返回MonadRandom上下文中的值。我想在a上下文中生成MonadRandom类型的值列表,即m [a]。我相信做这样的事情:

func = do
    xs <- map f [0..10]
    return xs

会生成一个值列表,每个值都在monadic上下文中,然后尝试从不在MonadRandom上下文中的列表中绘制

如果我的术语/理解不正确,我很抱歉,我是haskell的新手。

1 个答案:

答案 0 :(得分:2)

更新

使用MonadRandom进行编辑我认为您需要的只是mapM

import System.Random (randomRIO)

f :: Int -> IO Int
f n = randomRIO (n,n+n)

g :: [Int] -> IO [Int]
g xs = mapM f xs

例如

λ> g [1..3]
[1,4,5]
λ> g [1..3]
[1,3,4]
λ> g [1..3]
[1,4,6]

btw:当然你可以使用do

自己做
g :: [Int] -> IO [Int]
g [] = return []
g (x:xs) = do
  r <- f x
  rs <- g xs
  return (r:rs)

请记住不要在此处混淆列表和IO monad - 因此此处的do<-return位于IO - 这个答案的其余部分将在list-monad

首先,您的示例(如果f :: a -> [b])将创建值列表(您肯定已经发现) - 如果您想要展平它看起来如下(基本上你只需再拉出来)

现在我并不确切地知道你的目的地,但这里有一个简短的例子,说明如何在列表中使用do表示法:

看看这个功能:

combs :: [a] -> [b] -> [(a,b)]
combs xs ys = do
  x <- xs
  y <- ys
  return (x,y)

这是一个实际操作示例:

λ> combs [1..3] "Hi"
[(1,'H'),(1,'i'),(2,'H'),(2,'i'),(3,'H'),(3,'i')]

正如您所看到的,技巧是在所有x中绘制一个示例 xs(当然,您将完成所有操作 - 因此你可以把它想象成使用组合学)和y中的ys,然后用它们做一些事情(这里只做一个元组),最后return它。

现在你可以先以某种方式映射它(这里只是加倍xs):

combs :: [a] -> [b] -> [(a,b)]
combs xs ys = do
  x <- xs ++ xs
  y <- ys
  return (x,y)

它将拉出映射值:

λ> combs [1..3] "Hi"
[(1,'H'),(1,'i'),(2,'H'),(2,'i'),(3,'H'),(3,'i'),(1,'H'),(1,'i'),(2,'H'),(2,'i'),(3,'H'),(3,'i')]

这对你有帮助吗?

这是f自己创建列表的另一个:

func :: (a -> [b]) -> [a] -> [b]
func f xs = do
  x <- xs
  b <- f x
  return b

正如您所看到的那样,我们首先从x中提取xs,然后应用f获取b的列表,仅将其b <- f x拉出来然后只返回那些。

当然只是concatMap

实施例

λ> func (\x -> [x,x]) [1..5]
[1,1,2,2,3,3,4,4,5,5]

这是你要去的地方吗?