1

I am trying to write a function that sums integers supplied one per line and stops when 0 is input. I have this so far:

getInt :: IO Int          
getInt = do  
  s <- getLine
  return (read s)

sumInts :: IO Int
sumInts = do
  x<-getInt
  if x==0 then return 0 else return (x+sumInts)

but I get an error when I try to run it:

couldn't match expected type Int with actual type IO Int

Diana
  • 1,417
  • 5
  • 25
  • 48

2 Answers2

6

You are trying to add Int with IO Int in (x+sumInts).

Let's take this step by step:

getInt return an actions that when it's executed returns an "Int" and you execute it using <- :

x<-getInt

That means x have type Int.

In expression (x+sumInts) you use + which have a type of:

(+) :: Num a => a -> a -> a 

Haskell interfer the type and replace a with the type of x, which means + will have type of:

 (+) :: Int -> Int -> Int

and will expect as second parameter an Int.

You are providing as the second parameter sumInts which have a type IO Int and that's why you have that error couldn't match expected type Int with actual type IO Int.

To make it works you have to "get out" the value from IO action using <- like this:

sumInts :: IO Int
sumInts = do
  x<-getInt
  if x==0 
    then return 0 
    else do
         rest <- sumInts
         return (x+rest)

Another approach to solve ths, in a more readable, is using Applicative:

import Control.Applicative

getInt :: IO Int          
getInt = do  
  s <- getLine
  return (read s)

sumInts :: IO Int
sumInts = do
  x<-getInt
  if x==0 then return 0 else (x+) <$> sumInts 

The <$> function takes a function (in our case x+) an apply it on value inside an Applicative Functor (IO is instance of Applicative and Functor) and return that Functor with computation applied. Type of <$> is:

> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b

and for IO this will be :

(<$>) :: (a -> b) -> IO a -> IO b
(<$>) :: (Int -> Int) -> IO Int -> IO Int -- If we consider that a is an Int
Gabriel Ciubotaru
  • 1,042
  • 9
  • 22
1

Here:

x<-getInt
if x==0 then return 0 else return (x+sumInts)

x has a type Int, but sumInts is IO Int. I would recommend separating the IO part and the calculation part into different functions.

Eugene Sh.
  • 17,802
  • 8
  • 40
  • 61