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

时间:2015-05-08 11:35:58

标签: haskell

我正在尝试编写一个函数,该函数对每行提供的整数求和,并在输入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

匹配

2 个答案:

答案 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,但sumIntsIO Int。 我建议将IO部分和计算部分分成不同的功能。