[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