据我了解,您可以使用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的新手。
答案 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]
这是你要去的地方吗?