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