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:
我正在尝试编写一个函数,该函数对每行提供的整数求和,并在输入0时停止。到目前为止我有这个:
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
无法将预期类型Int与实际类型IO Int匹配
2 个解决方案
#1
You are trying to add Int with IO Int in (x+sumInts)
.
您正尝试在(x + sumInts)中添加带IO Int的Int。
Let's take this step by step:
让我们一步一步:
getInt return an actions that when it's executed returns an "Int" and you execute it using <-
:
getInt返回一个动作,当它执行时返回一个“Int”并用< - :执行它
x<-getInt
That means x have type Int
.
这意味着x具有Int类型。
In expression (x+sumInts)
you use +
which have a type of:
在表达式(x + sumInts)中,您使用+,其类型为:
(+) :: Num a => a -> a -> a
Haskell interfer the type and replace a
with the type of x, which means +
will have type of:
Haskell干涉类型并用x的类型替换a,这意味着+将具有以下类型:
(+) :: Int -> Int -> Int
and will expect as second parameter an Int
.
并期望作为第二个参数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
.
您提供的第二个参数是具有IO Int类型的sumInts,这就是为什么您的错误无法将期望类型Int与实际类型IO Int匹配。
To make it works you have to "get out" the value from IO action using <-
like this:
为了使它工作,你必须使用< - 从这个:“取出”来自IO动作的值:
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:
另一种解决方法,更具可读性,是使用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:
<$>函数接受一个函数(在我们的例子中是x +),将它应用于Applicative Functor中的值(IO是Applicative和Functor的实例),并返回应用了计算的Functor。 <$>的类型是:
> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
and for IO this will be :
对于IO,这将是:
(<$>) :: (a -> b) -> IO a -> IO b
(<$>) :: (Int -> Int) -> IO Int -> IO Int -- If we consider that a is an Int
#2
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.
x的类型为Int,但sumInts为IO Int。我建议将IO部分和计算部分分成不同的功能。
#1
You are trying to add Int with IO Int in (x+sumInts)
.
您正尝试在(x + sumInts)中添加带IO Int的Int。
Let's take this step by step:
让我们一步一步:
getInt return an actions that when it's executed returns an "Int" and you execute it using <-
:
getInt返回一个动作,当它执行时返回一个“Int”并用< - :执行它
x<-getInt
That means x have type Int
.
这意味着x具有Int类型。
In expression (x+sumInts)
you use +
which have a type of:
在表达式(x + sumInts)中,您使用+,其类型为:
(+) :: Num a => a -> a -> a
Haskell interfer the type and replace a
with the type of x, which means +
will have type of:
Haskell干涉类型并用x的类型替换a,这意味着+将具有以下类型:
(+) :: Int -> Int -> Int
and will expect as second parameter an Int
.
并期望作为第二个参数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
.
您提供的第二个参数是具有IO Int类型的sumInts,这就是为什么您的错误无法将期望类型Int与实际类型IO Int匹配。
To make it works you have to "get out" the value from IO action using <-
like this:
为了使它工作,你必须使用< - 从这个:“取出”来自IO动作的值:
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:
另一种解决方法,更具可读性,是使用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:
<$>函数接受一个函数(在我们的例子中是x +),将它应用于Applicative Functor中的值(IO是Applicative和Functor的实例),并返回应用了计算的Functor。 <$>的类型是:
> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
and for IO this will be :
对于IO,这将是:
(<$>) :: (a -> b) -> IO a -> IO b
(<$>) :: (Int -> Int) -> IO Int -> IO Int -- If we consider that a is an Int
#2
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.
x的类型为Int,但sumInts为IO Int。我建议将IO部分和计算部分分成不同的功能。