简体   繁体   中英

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. 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 . Using them both returns a list of 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.

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. It is a list of I/O actions that generate numbers. The I/O wasn't executed yet, so in your case the random number generator hasn't actually generated the numbers.

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:

do the_numbers <- sequence your_list
   return $ sum the_numbers

Alternatively you could use the foldM function to write a monadic fold:

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:

fmap sum (sequence your_list)

Or use the infix synonym <$> :

sum <$> sequence your_list

How about something like the following using 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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