所以我在与Haskell愚弄,试图自己学习它。我试图解决某个问题,我应该创建一个随机数列表,然后对它们进行总结。
我有使用getStdRandom
和randomR
生成它们的代码。使用它们都会返回IO Float
:[IO Float]
现在,当我尝试使用say foldl或foldr总结列表,或者甚至尝试简单的递归求和时,我会得到错误等等 - 据我所知这是因为IO Float
是一个monad,所以我需要做一些Haskell魔术才能让它发挥作用。
我一直在谷歌上搜索,但却找不到有用的东西。
有没有办法总结清单?甚至将其转换为浮点列表,以便更容易在代码的其他部分中解决?
答案 0 :(得分:9)
请注意,类型为[IO Float]
的列表不是数字列表。它是生成数字的I / O操作列表。 I / O尚未执行,因此在您的情况下,随机数生成器实际上并未生成数字。
您可以使用sequence :: Monad m => [m a] -> m [a]
功能将IO操作列表组合到一个提供结果列表的IO操作中:
do the_numbers <- sequence your_list
return $ sum the_numbers
或者你可以使用foldM
函数来编写一个monadic折叠:
sumIONumbers :: [IO Float] -> IO Float
sumIONumbers xs = foldM f 0.0 xs
where
f acc mVal = do
val <- mVal -- extract the Float from the IO
return $ acc + val
正如评论中所述,您还可以利用每个Monad
也是Functor
这一事实(这是在较新版本中强制执行),因此您可以使用fmap :: Functor f => (a -> b) -> f a -> f b
来在IO中应用一个函数:
fmap sum (sequence your_list)
或使用中缀同义词<$>
:
sum <$> sequence your_list
答案 1 :(得分:1)
如何使用liftM来完成以下内容:
import System.Random
import Control.Monad
rnd :: IO Float
rnd = getStdRandom (randomR (0.0,1.0))
main = do
let l = map (\_ -> rnd) [1..10]
n <- foldl (liftM2 (+)) (return (0 :: Float)) l
print n