简体   繁体   English

总结IO浮动列表:[Haskell中的[IO Float]

[英]Summing up a list of IO Float: [IO Float] in Haskell

So I'm fooling around a bit with Haskell, trying to learn it by myself. 所以我在和Haskell鬼混,试图自己学习。 I'm trying to solve a certain question where I'm supposed to create a list of random numbers and then sum them up. 我正在尝试解决一个特定的问题,我应该在其中创建一个随机数列表,然后对其进行汇总。

I have the code to generate them - using getStdRandom and randomR . 我有生成它们的代码-使用getStdRandomrandomR Using them both returns a list of IO Float : [IO Float] 都使用它们都返回IO Float的列表: [IO Float]

Now, when I try to sum up the list using say foldl or foldr, or even trying a simple recursion summation, I get errors and such - to my understanding this is because IO Float is a monad, so I need to do some Haskell magic to get it to work. 现在,当我尝试使用foldl或foldr来汇总列表,甚至尝试简单的递归求和时,都会遇到错误等-据我了解,这是因为IO Float是monad,所以我需要做一些Haskell魔术使它工作。

I've been googling around and haven't found something that works. 我一直在四处搜寻,却没有找到有效的方法。

Is there any way to sum up the list? 有什么办法汇总清单? or even convert it into a list of floats so that its easier to work around in other parts of the code? 甚至将其转换为浮点数列表,以便其在代码的其他部分更容易解决?

Note that a list with type [IO Float] is not a list of numbers. 请注意,类型为[IO Float]的列表不是数字列表。 It is a list of I/O actions that generate numbers. 它是生成数字的I / O操作的列表。 The I/O wasn't executed yet, so in your case the random number generator hasn't actually generated the numbers. 该I / O尚未执行,因此在您的情况下,随机数生成器实际上尚未生成数字。

You can use the sequence :: Monad m => [ma] -> m [a] function to combine the list of IO actions into a single IO action that provides a list of results: 您可以使用sequence :: Monad m => [ma] -> m [a]函数将IO操作列表组合为一个提供结果列表的IO操作:

do the_numbers <- sequence your_list
   return $ sum the_numbers

Alternatively you could use the foldM function to write a monadic fold: 或者,您可以使用foldM函数编写单折:

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

As noted in the comments you can also make use of the fact that every Monad is also a Functor (this is enforced in newer versions) and thus you can use fmap :: Functor f => (a -> b) -> fa -> fb to apply a function inside the IO: 如评论中所述,您还可以利用以下事实:每个Monad也是Functor (在新版本中强制执行),因此您可以使用fmap :: Functor f => (a -> b) -> fa -> fb在IO中应用功能:

fmap sum (sequence your_list)

Or use the infix synonym <$> : 或使用中缀同义词<$>

sum <$> sequence your_list

How about something like the following using liftM: 如何使用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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM