Haskell - 从键盘读取的整数之和

时间:2022-04-10 16:08:56

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部分和计算部分分成不同的功能。