总结一下IO Float列表:Haskell中的[IO Float]

时间:2016-04-09 09:47:56

标签: list haskell functional-programming sum monads

所以我在与Haskell愚弄,试图自己学习它。我试图解决某个问题,我应该创建一个随机数列表,然后对它们进行总结。

我有使用getStdRandomrandomR生成它们的代码。使用它们都会返回IO Float[IO Float]

的列表

现在,当我尝试使用say foldl或foldr总结列表,或者甚至尝试简单的递归求和时,我会得到错误等等 - 据我所知这是因为IO Float是一个monad,所以我需要做一些Haskell魔术才能让它发挥作用。

我一直在谷歌上搜索,但却找不到有用的东西。

有没有办法总结清单?甚至将其转换为浮点列表,以便更容易在代码的其他部分中解决?

2 个答案:

答案 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