Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Help with Haskell IO typing

Tags:

haskell

I need some help with types in Haskell...

Here's the code I'm working on:

loadManyPeople :: [FilePath] →  IO [Person]
loadManyPeople fs = do
   return $ concat $ map loadPeople fs

loadPeople :: FilePath →  IO [Person]
loadPeople file = do
   lines ←  getLines file
   return $ map parsePerson lines

loadPeople is fine. I want loadManyPeople to load all the Persons from each file, then concat them into one list of Persons.

I'm new to Haskell and need help with getting the types to work out.

Thanks for the help. Alex

like image 256
Alex Baranosky Avatar asked Dec 17 '22 20:12

Alex Baranosky


1 Answers

loadPeople gives you an IO [Person], so map loadPeople gives you a [IO [Person]], however to use concat, you'd need a [[Person]].

To fix this, you can use sequence, which is a function of type [IO a] -> IO [a], so you can do the following:

loadManyPeople fs = do
   manyPeople <- sequence $ map loadPeople fs
   return $ concat manyPeople

However there's a shortcut for using map and then sequence: mapM which has type (a -> IO b) -> [a] -> IO [b]. With mapM your code looks like this:

loadManyPeople fs = do
   manyPeople <- mapM loadPeople fs
   return $ concat manyPeople

This can be written more succinctly using Applicative:

import Control.Applicative
loadManyPeople fs = concat <$> mapM loadPeople fs
like image 63
sepp2k Avatar answered Jan 05 '23 04:01

sepp2k