简体   繁体   English

在单子上下文中生成列表

[英]Generating lists in a monadic context

As I understand, you can use the 'draw from' (<-) keyword in haskell to take values out of a monadic context in do-notation: 据我了解,您可以在haskell中使用'draw from' (<-)关键字从do-notation中的一元上下文中获取值:

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

How would I apply this when generating lists? 生成列表时如何应用? Say I am mapping a function f :: (MonadRandom m) => Int -> ma that takes an integer and returns a value in a MonadRandom context. 假设我正在映射一个函数f :: (MonadRandom m) => Int -> ma ,它接受一个整数并在MonadRandom上下文中返回一个值。 I want to generate a list of values of type a inside a MonadRandom context ie m [a] . 我想在MonadRandom上下文即m [a]生成类型为a的值的列表。 I believe doing something like this: 我相信这样做是这样的:

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

would generate a list of values, each in a monadic context and then try to draw from the list which is not in the MonadRandom context 会生成一个值列表,每个值都在单子上下文中,然后尝试从不在MonadRandom上下文中的列表中进行绘制

Apologies if my terminology/understanding is incorrect, I am new to haskell. 抱歉,如果我的术语/理解不正确,我是Haskell的新手。

update 更新

for your edit with the MonadRandom I think all you need is mapM : 对于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

example

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

btw: of course you can do this yourself using do : 顺便说一句:当然,您可以使用do自己执行此do

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

just remember not to mix up the list and the IO monad here - so the do , <- and return here is in IO - for the rest of this answer it will be in the list-monad 只是要记住不要在此处将列表和IO monad混合在一起-因此, do<-和此处returnIO -对于此答案的其余部分,它将在list-monad中


First your example (if f :: a -> [b] ) will create a list of list of values (which you surely found out already) - if you want to flatten it look below (basically you just have to pull out once more) 首先,您的示例(如果f :: a -> [b] )将创建一个值列表的列表 (您肯定已经发现了)-如果您想将其展平到下面(基本上,您只需再次拉出) )


Right now I don't understand exactly where you are going for, but here is a short example of how you can use the do notation with lists: 目前,我还不清楚您要去哪里,但是这里有一个简短的示例,说明如何将do符号与列表一起使用:

Look at this function: 看一下这个功能:

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

here is an example of it in action: 这是一个实际的例子:

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

As you can see the trick is to draw an example x out of all xs (of course you will do all - therefore you can think of this as working with combinatorics) and a y out of ys and then do something with them (here just make a tuple) and finally return ing it. 正如你所看到的, 关键是要画一个例子 x掉所有的xs (你当然会尽一切-所以你可以认为这与组合数学工作)和y出来的ys ,然后做他们的东西(这里只是做一个元组),最后return它。

Now of course you can first map it somehow (here just doubling the xs ): 现在,您当然可以先以某种方式对其进行映射了(这里只需将xs加倍):

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

and it will pull out of the mapped values: 它将拉出映射的值:

λ> 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')]

does this help you? 这对您有帮助吗?


here is another one where f creates a list itself: 这是f本身创建列表的另一个:

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

as you can see first we pull out an x from xs , apply f to get a lists of b s only to pull them out with b <- fx and then just returning those. 如您所见,首先我们从xs拉出一个x ,应用f来获得b s的列表,然后只用b <- fx将它们拉出,然后返回它们。

Which is of course just concatMap 当然,这只是concatMap

Example

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

is this where you are going for? 这是您要去的地方吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM