Problems when trying to solve yaht exercise 3.10

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Problems when trying to solve yaht exercise 3.10

ZelluX
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?

Thanks for your reply
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090320/1ee32429/attachment-0001.htm
Reply | Threaded
Open this post in threaded view
|

Problems when trying to solve yaht exercise 3.10

Andrew Wagner
Ah, you came very close to getting this right. The problem is on your two
putStrLn lines. For example, putStrLn "The sum is " ++ show(sum)
This parses as (putStrLn "The sum is ") ++ show(sum). Thus, it's trying to
use ++ on an IO () and a string. This obviously won't work. You need one of
the following:

putStrLn ("The sum is " ++ show(sum))
putStrLn $ "The sum is " ++ show(sum)

Ditto for the product line. Also, if I can make 2 other quick comments:
product and sum are already defined in the prelude, so there's no need to
define them here. You should also get used to putting type signatures on
your functions, because it's a good practice. Otherwise, good job!

2009/3/20 ZelluX <[hidden email]>

> 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?
>
> Thanks for your reply
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090320/97683cc6/attachment.htm
Reply | Threaded
Open this post in threaded view
|

Problems when trying to solve yaht exercise 3.10

Thomas Davie
In reply to this post by ZelluX

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

Reply | Threaded
Open this post in threaded view
|

Problems when trying to solve yaht exercise 3.10

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

On Fri, Mar 20, 2009 at 9:00 PM, Thomas Davie <[hidden email]> 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