在 monadic 上下文中生成列表
Generating lists in a monadic context
据我了解,您可以在 haskell 中使用 'draw from' (<-)
关键字从 do-notation 中的 monadic 上下文中获取值:
func = do
x <- getRandom
let y = (x + 1)
return y
生成列表时如何应用它?假设我正在映射一个函数 f :: (MonadRandom m) => Int -> m a
,它在 MonadRandom
上下文中接受一个整数和 returns 一个值。我想在 MonadRandom
上下文中生成 a
类型的值列表,即 m [a]
。我相信做这样的事情:
func = do
xs <- map f [0..10]
return xs
将生成一个值列表,每个值都在一个单子上下文中,然后尝试从不在 MonadRandom
上下文中的列表中提取
抱歉,如果我的 terminology/understanding 不正确,我是 haskell 的新手。
更新
对于您使用 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]
顺便说一句:当然你可以自己使用 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
中
首先,您的示例 (if f :: a -> [b]
) 将创建一个 值列表列表 (您肯定已经发现了)- 如果您想要 flatten 看下面(基本上你只需要再拉一次)
现在我不明白你要去哪里,但这里有一个简短的例子,说明如何将 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')]
如您所见,技巧 是从所有 xs
(当然你会做所有的事情——因此你可以认为这是在使用组合数学)和 ys
中的 y
然后用它们做一些事情(这里只是做一个元组)最后 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
如您所见,我们首先从 xs
中提取了一个 x
,应用 f
来获取 b
的列表,然后使用 b <- f x
然后只返回那些。
这当然只是concatMap
示例
λ> func (\x -> [x,x]) [1..5]
[1,1,2,2,3,3,4,4,5,5]
这是你要去的地方吗?
据我了解,您可以在 haskell 中使用 'draw from' (<-)
关键字从 do-notation 中的 monadic 上下文中获取值:
func = do
x <- getRandom
let y = (x + 1)
return y
生成列表时如何应用它?假设我正在映射一个函数 f :: (MonadRandom m) => Int -> m a
,它在 MonadRandom
上下文中接受一个整数和 returns 一个值。我想在 MonadRandom
上下文中生成 a
类型的值列表,即 m [a]
。我相信做这样的事情:
func = do
xs <- map f [0..10]
return xs
将生成一个值列表,每个值都在一个单子上下文中,然后尝试从不在 MonadRandom
上下文中的列表中提取
抱歉,如果我的 terminology/understanding 不正确,我是 haskell 的新手。
更新
对于您使用 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]
顺便说一句:当然你可以自己使用 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
首先,您的示例 (if f :: a -> [b]
) 将创建一个 值列表列表 (您肯定已经发现了)- 如果您想要 flatten 看下面(基本上你只需要再拉一次)
现在我不明白你要去哪里,但这里有一个简短的例子,说明如何将 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')]
如您所见,技巧 是从所有 xs
(当然你会做所有的事情——因此你可以认为这是在使用组合数学)和 ys
中的 y
然后用它们做一些事情(这里只是做一个元组)最后 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
如您所见,我们首先从 xs
中提取了一个 x
,应用 f
来获取 b
的列表,然后使用 b <- f x
然后只返回那些。
这当然只是concatMap
示例
λ> func (\x -> [x,x]) [1..5]
[1,1,2,2,3,3,4,4,5,5]
这是你要去的地方吗?