我正在尝试编写一个函数,该函数对每行提供的整数求和,并在输入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)
但是当我尝试运行它时出现错误:
无法将预期类型Int与实际类型IO Int
匹配
答案 0 :(得分:6)
您正尝试在(x+sumInts)
中添加带IO Int的Int。
让我们一步一步:
getInt返回一个动作,当它被执行时返回一个&#34; Int&#34;然后使用<-
执行它:
x<-getInt
这意味着x的类型为Int
。
在表达式(x+sumInts)
中,您使用+
,其类型为:
(+) :: Num a => a -> a -> a
Haskell干扰类型并将a
替换为x的类型,这意味着+
将具有以下类型:
(+) :: Int -> Int -> Int
并期望第二个参数为Int
。
您提供的第二个参数sumInts
的类型为IO Int
,这就是您遇到错误couldn't match expected type Int with actual type IO Int
的原因。
为了使它有效,你必须&#34;离开&#34;使用<-
的IO操作的值如下:
sumInts :: IO Int
sumInts = do
x<-getInt
if x==0
then return 0
else do
rest <- sumInts
return (x+rest)
另一种解决方法,更具可读性,是使用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
<$>
函数接受一个函数(在我们的例子中为x+
),将它应用于Applicative Functor中的值(IO是Applicative和Functor的实例),并返回应用了计算的Functor。
<$>
的类型为:
> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
对于IO,这将是:
(<$>) :: (a -> b) -> IO a -> IO b
(<$>) :: (Int -> Int) -> IO Int -> IO Int -- If we consider that a is an Int
答案 1 :(得分:1)
下面:
x<-getInt
if x==0 then return 0 else return (x+sumInts)
x
的类型为Int
,但sumInts
为IO Int
。
我建议将IO部分和计算部分分成不同的功能。