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

use*_*680 1 monads haskell functional-programming sum list

所以我在哈斯克尔身上愚弄,试着自己去学习.我正在尝试解决某个问题,我应该创建一个随机数列表然后总结它们.

我有生成它们的代码 - 使用getStdRandomrandomR.使用它们都返回一个列表IO Float:[IO Float]

现在,当我尝试使用say foldl或foldr总结列表,或者甚至尝试简单的递归求和时,我得到错误等等 - 据我所知这是因为IO Float是monad,所以我需要做一些Haskell魔法来获取它工作.

我一直在谷歌搜索,并没有找到有用的东西.

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

Bak*_*riu 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
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用该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
Run Code Online (Sandbox Code Playgroud)

如评论中所述,您还可以利用每个Monad都是Functor(这在较新版本中强制执行)的事实,因此您可以使用fmap :: Functor f => (a -> b) -> f a -> f b在IO中应用函数:

fmap sum (sequence your_list)
Run Code Online (Sandbox Code Playgroud)

或者使用中缀同义词<$>:

sum <$> sequence your_list
Run Code Online (Sandbox Code Playgroud)

  • 第一个`do`语句可以简化为`fmap sum(sequence yourList)`或`sum <$> sequence yourList`.(其中[`fmap :: Functor f =>(a - > b) - > fa - > fb`](http://hackage.haskell.org/package/base-4.8.2.0/docs/Prelude.html# v:fmap)和`(<$>)= fmap`) (3认同)
  • "**不是**一个数字列表" - 确切地说.一个简单的方法是多次评估`sequence your_list`:每次都会得到不同的结果! (2认同)