我可能在这里对您的代码读得过多,所以如果我错了,请纠正我,但看起来您对 Haskell 程序的工作方式感到困惑,尤其是对什么return
意思感到困惑。
return
Haskell 中的 return 语句不是您可能熟悉的许多命令式编程语言。return
在 Haskell 中是一个函数。像任何其他函数一样,您将其应用于参数以计算值。它对流控制没有影响,特别是它不会导致它的参数被“返回”为你所在的函数计算的值。
对于IO
monad,return
是这种类型的函数:return :: a -> IO a
,这意味着它接受任何类型的值并为您提供“该IO
类型的版本”中的值。在 的特定情况下return
,它为您提供了一个将产生该值的无操作 IO 计算。
这个:
summ :: Integer -> Integer -> Integer -> IO Integer
summ x1 x2 x3 = return(x1+x2+x3)
对于 Haskell 程序员来说,这是一个非常奇怪的功能。没有必要做 IO 来计算 3 个整数的和,那么为什么结果类型是IO Integer
?在我看来,你试图写这个:
summ :: Integer -> Integer -> Integer -> Integer
summ x1 x2 x3 = return(x1+x2+x3)
这会给你一个关于Integer
不是一元类型的类型错误。您可以通过更改类型来解决此问题,但类型是对 3 个整数求和的正确表达式,因此将其更改为其他内容相当奇怪。由于return
根本不需要计算函数的结果,因此您可以这样做:
summ :: Integer -> Integer -> Integer -> Integer
summ x1 x2 x3 = x1+x2+x3
同样,您的sumThree
功能也很奇怪。当您在 Haskell 解释器中执行此操作时:
*Main> sumThree
Please enter three integers:
1
2
3
Their sum is:
(1,2,3)
解释器正在评估sumThree
IO 操作,它要求您输入 3 个整数并打印“它们的总和为:”,并产生值(1, 2, 3)
。动作本身在sumThree
之后不打印任何内容"Their sum is:"
,它是为您打印的解释器,它打印的是执行产生的值sumThree
。
这是 do 块中的最后一件事,它决定了sumThree
;产生的值。在这种情况下,就是return(x1,x2,x3)
。因此,您可以看到这不可能是 3 个数字的总和,因为您非常明确地采用 tuple (x1, x2, x3)
,将其包装成一个IO
带有 的动作return
,然后就是结果。
你的倒数第二行:
summ x1 x2 x3
是一个IO
动作(感谢Integer -> Integer -> Integer -> IO Integer
for的类型summ
)。所以它被允许坐在那里,它被“执行”以产生它的价值,但你对它不做任何事情!
所以有两件事:
summ
return
根本不需要
sumThree
实际上应该打印您想要打印的内容
把它们放在一起你可以得到这样的东西:
summ :: Integer -> Integer -> Integer -> Integer
summ x1 x2 x3 = x1 + x2 + x3
sumThree :: IO ()
sumThree = do putStr "Please enter tree integers:"
x1 <- getInteger
x2 <- getInteger
x3 <- getInteger
putStr "Their Sum is: "
putStr (show (summ x1 x2 x3))
那是如果你不想sumThree
产生总和以及打印它。如果sumThree
应该产生价值以及打印它,你会想要更像这样的东西:
summ :: Integer -> Integer -> Integer -> Integer
summ x1 x2 x3 = x1 + x2 + x3
sumThree :: IO Integer
sumThree = do putStr "Please enter tree integers:"
x1 <- getInteger
x2 <- getInteger
x3 <- getInteger
putStr "Their Sum is: "
putStr (show (summ x1 x2 x3))
return (summ x1 x2 x3)