[Haskell-beginners] Problems when trying to solve yaht exercise 3.10

ZelluX zellux at gmail.com
Fri Mar 20 09:05:00 EDT 2009


Got it. Many thanks to Thomas Davie's and Andrew Wagner's replies.  ^_^

On Fri, Mar 20, 2009 at 9:00 PM, Thomas Davie <tom.davie at gmail.com> wrote:

>
> On 20 Mar 2009, at 13:45, ZelluX wrote:
>
>  Hi, all
>>
>> I'm new to haskell and currently reading yaht. I find some problems when
>> trying to solve exercise 3.10.
>>
>> The exersices asks to read a list of numbers terminated by a zero, and
>> figure out the sum and product of the list. My program is as follows:
>>
>> ex3_10 = do
>>  hSetBuffering stdin LineBuffering
>>  numbers <- getNumber
>>  let sum = foldr (+) 0 numbers
>>      product = foldr (*) 1 numbers
>>  putStrLn "The sum is " ++ show(sum)
>>  putStrLn "The product is " ++ show(product)
>>
>> getNumber = do
>>  putStrLn "Give me a number (or 0 to stop):"
>>  num <- getLine
>>  if read num == 0
>>     then return []
>>     else do
>>       rest <- getNumber
>>       return (read num : rest)
>>
>> But when i load the program, ghci reports error:
>>    Couldn't match expected type `[a]' against inferred type `IO ()'
>>    In the first argument of `(++)', namely `putStrLn "The sum is "'
>>    In a stmt of a 'do' expression:
>>          putStrLn "The sum is " ++ show (sum)
>>
>> And i just don't understand the first sentence. Could you tell what does
>> it mean?
>>
>
> It means that you can't use ++ on an IO action, ++'s type reveals why:
>
> (++) :: [a] -> [a] -> [a]
>
> It accepts two lists, not a list and an IO action.  So the question then
> is, which IO action are you using ++ on?  The answer is (putStrLn "The sum
> is").  Your last two statements are being parsed as:
>
> (putStrLn "The sum is ") ++ (show sum)
> (putStrLn "The product is ") ++ (show product)
>
> As a random aside, it's usually a good plan in Haskell to get out of IO
> based computations as fast as possible, and use pure functions instead.  You
> might want to consider something like this:
>
> ex3_10 = do
>  hSetLineBuffering stdin LineBuffering
>  interact sumAndProduct
>
> sumAndProduct :: String -> String
> sumAndProduct = (\ns -> sumText ns ++ productText ns) . map read . lines
>
> sumText :: (Num a, Show a) => [a] -> String
> sumText = ("The sum is " ++) . show . sum
>
> productText :: (Num a, Show a) => [a] -> String
> productText = ("The product is " ++) . show . product
>
> Why might you want to do this?  Well, firstly, the code becomes more
> readable, secondly, a computation that was not sequential is no longer
> described as being sequential, and finally, the results are more composible.
>  We can now use sumText and productText, safe in the knowledge that they
> will never have side effects etc.
>
> Bob
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090320/95013883/attachment.htm


More information about the Beginners mailing list