[Haskell-beginners] Reading Multiple Files and Iterate Function Application

Thomas Miedema thomasmiedema at gmail.com
Mon Oct 11 13:20:11 EDT 2010


Hi,

replace
let fl = getAllLengths nums

by
fl <- getAllLengths nums

, since getAllLengths returns a monadic action.

The author of the following book is much better at explaining why this is so
than I am: http://learnonlineyouahaskell.com/
<http://learnyouahaskell.com/>. May
I suggest you read it cover to cover, it's really really good. It is
probably the best way to learn Haskell at the moment, together with trying
out code snippets like you're doing right now.

Regards,
Thomas



On Mon, Oct 11, 2010 at 6:06 PM, Lorenzo Isella <lorenzo.isella at gmail.com>wrote:

> Thanks a lot Daniel, but I am a bit lost (up to not long ago I did not even
> know the existence of a control monad...and some unstructured reading did
> not help).
> Some online research about mapM and fmap led me here
> http://en.wikibooks.org/wiki/Haskell/Category_theory
> and I think I am a bit astray at this point ;-)
>
> Why does my "simple" snippet below raise a number of errors?
>
> Cheers
>
> Lorenzo
>
>
> import Data.Ord
>
> import Data.List
>
> main :: IO ()
>
> main = do
>
>  let nums=[1,2]
>
>  let fl = getAllLengths nums
>
>  putStrLn "fl is, "
>  print fl
>
>
>
> filename :: Int -> FilePath
> filename i = "file" ++ show i ++ ".dat"
>
> fileLength :: FilePath -> IO Int
> fileLength file = fmap length (readFile file)
>
> getAllLengths :: [Int] -> IO [Int]
> getAllLengths nums = mapM (fileLength . filename) nums
>
>
>
> On 10/11/2010 05:21 PM, Daniel Fischer wrote:
>
>> On Monday 11 October 2010 16:56:58, Lorenzo Isella wrote:
>>
>>> Dear All,
>>> Another I/O question.
>>> Let us say that you are given a list of files file1.dat,
>>> file2.dat...file10.dat and so on (i.e. every file is indexed by a number
>>> and every file is a single column where every entry is a string without
>>> spaces).
>>> In the snippet below I read file1.dat, convert it to a list and then
>>> print out its length.
>>> Now, how can I iterate the process on file1.dat, file2.dat and file3.dat
>>> and store the lengths in a list?
>>>
>>
>> fileLength :: FilePath ->  IO Int
>> fileLength file = fmap length (readFile file)
>>
>> filename :: Int ->  FilePath
>> filename i = "file" ++ show i ++ ".dat"
>>
>> getAllLengths :: [Int] ->  IO [Int]
>> getAllLengths nums = mapM (fileLength . filename) nums
>>
>>
>> If you want something other than the character count, instead of
>> fileLength
>> use e.g.
>>
>> countLines :: FilePath ->  IO Int
>> countLines file = fmap (length . lines) (readFile file)
>>
>> or whatever you're interested in.
>>
>> Another nice thing is often forM (from Control.Monad)
>>
>> forM nums $ \i ->  do
>>    let filename = "file" ++ show i ++ ".dat"
>>    contents<- readFile filename
>>    let result = function contents
>>    doSomethingOrNot
>>    return result
>>
>>  I would like to map the file reading and following operations on the
>>> list [1,2.3], but that is giving me a headache.
>>> It is relatively easy to create the file name
>>>
>>> filename="file"++(show i)++".dat"   , for i=1,2,3
>>>
>>> but it the the iteration part that is giving me troubles.
>>> Any suggestion is appreciated.
>>> Cheers
>>>
>>> Lorenzo
>>>
>>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20101011/91365a84/attachment.html


More information about the Beginners mailing list