Debugging 尝试在函数中调用putStrLn时出错
我试图在Haskell函数中放置一个“print out”函数调用 (一条简单的调试消息) 下面是我的代码和来自编译器(GHC 6.10)的错误消息 我不太明白为什么它把Debugging 尝试在函数中调用putStrLn时出错,debugging,haskell,Debugging,Haskell,我试图在Haskell函数中放置一个“print out”函数调用 (一条简单的调试消息) 下面是我的代码和来自编译器(GHC 6.10)的错误消息 我不太明白为什么它把putStr调用和空数组混为一谈 空数组是特定情况下的返回值(打印输出消息目前实际上只是一个存根) 你知道为什么这不起作用吗 我的代码: isAFactor :: Integer -> Integer -> Bool isAFactor x y = x `mod` y == 0 findFactors :: Integer
putStr
调用和空数组混为一谈
空数组是特定情况下的返回值(打印输出消息目前实际上只是一个存根)
你知道为什么这不起作用吗
我的代码:
isAFactor :: Integer -> Integer -> Bool
isAFactor x y = x `mod` y == 0
findFactors :: Integer -> Integer -> [Integer]
findFactors counter num =
let quotient = div num 2
in
if(counter > quotient)
then do
putStrLn ("factorList is : " ++ show quotient) (*** Line 10***)
[]
else if(isAFactor num counter)
then [counter] ++ [quotient] ++ findFactors (counter + 1) num
else
findFactors (counter + 1) num
isAFactor::Integer->Integer->Bool
isAFactor x y=x`mod`y==0
findFactors::Integer->Integer->[Integer]
findFactors计数器数量=
让商=div num 2
在里面
if(计数器>商)
那就做吧
putStrLn(“factorList是:”++显示商)(***第10行***)
[]
else if(isAFactor num计数器)
然后是[计数器]++[商]++findFactors(计数器+1)num
其他的
findFactors(计数器+1)数量
来自ghc的错误
test.hs:10:4:
Couldn't match expected type `[a] -> [Integer]'
against inferred type `IO ()'
In the expression:
putStrLn ("factorList is : " ++ show quotient) []
In the expression:
do putStrLn ("factorList is : " ++ show quotient) []
In the expression:
if (counter > quotient) then
do putStrLn ("factorList is : " ++ show quotient) []
else
if (isAFactor num counter) then
[counter] ++ [quotient] ++ findFactors (counter + 1) num
else
findFactors (counter + 1) num
测试。hs:10:4:
无法匹配预期的类型“[a]->[Integer]”
针对推断类型'IO()'
在表达式中:
putStrLn(“factorList是:”++显示商)[]
在表达式中:
do putStrLn(“factorList是:+++显示商)[]
在表达式中:
如果(计数器>商),则
do putStrLn(“factorList是:+++显示商)[]
其他的
如果(isAFactor num计数器),则
[计数器]++[商]++findFactors(计数器+1)num
其他的
findFactors(计数器+1)数量
记住Haskell是一种函数式语言,这一点很重要。这意味着函数不允许有任何副作用,包括将调试消息打印到屏幕上 然而,打破这种纯度是可能的,它在调试中是有用的。看看这个模块。在那里你可以找到一个函数
trace::String->a->a
。您可以在代码中使用它,如下所示:
import Debug.Trace
isAFactor :: Integer -> Integer -> Bool
isAFactor x y = x `mod` y == 0
findFactors :: Integer -> Integer -> [Integer]
findFactors counter num =
let quotient = div num 2
in
if(counter > quotient)
then trace ("factorList is: " ++ show quotient) []
else if(isAFactor num counter)
then [counter] ++ [quotient] ++ findFactors (counter + 1) num
else
findFactors (counter + 1) num
正如评论所建议的那样:
哈斯克尔也是一种语言。在实际需要结果之前,不会对表达式求值。在惰性设置中使用trace函数可能会有点混乱,因为在将跟踪消息打印到屏幕上时(如果打印的话)并不总是容易理解的
由于haskell是一种非常不同的语言,因此最好尝试以同样不同的方式开发程序。尝试对函数进行推理,而不是使用trace
和类似的“非纯”结构。学习利用Haskell强大的类型系统,并在通过类型检查器后使用(例如)测试您的函数。更新了说明
问题是Haskell中的IO是一元的,以do开头的块是将一元表达式(有时称为语句)与一元运算符组合在一起的语法糖。在本例中,所讨论的monad是IO monad,这可以从对putStrLn的调用中推断出来。do
块第二行的[]
实际上不是整个do块的值,而是putStrLn的最后一个参数;并不是说它接受第二个参数,而是编译器甚至没有弄清楚这一点,因为它会在前面终止,并出现您引用的类型错误。要使该行成为命令,您必须将另一个一元函数放在它前面(例如,return[]
)。不过,我并不是说这会帮助你解决问题
类型错误源于IO一元表达式始终具有类型IO
;在您的情况下,do
块也有此类型,这显然与签名中指定的类型[Integer]
不兼容
一般来说,因为Haskell是一种带有单声道IO的纯函数式语言,一旦进入IO单声道,就没有出路了,这是不连贯的。i、 例如,如果一个函数有一个包含IO操作的
do
块,那么它的签名必然包含IO
类型,调用该函数的所有其他函数的签名也必然包含IO
类型,等等。(其他monad确实提供了“退出”函数,但IO monad没有。)Jonas的帖子很好地回答了你的问题,因此,我将为您提供findFactors函数的惯用重写。当我第一次学习时,我发现它对我很有帮助
因此,通过查看从1
到n/2
的每个数字,检查它是否是n
的因子,并建立一个包含这些因子的列表,您可以找到给定数字的所有因子n
您的版本(只需进行少量修改即可使用):
对格式进行了一些更改,使其更具可读性:
findFactors :: Integer -> Integer -> [Integer]
findFactors counter num
| counter > div num 2 = []
| otherwise = if num `isAFactor` counter
then counter:findFactors (counter+1) num
else findFactors (counter + 1) num
这很好,但在两个方面都不太理想。首先,每次调用findFactors
时,它都会重新计算商,即n/2
除法(尽管ghc-O2
似乎意识到这一点,并且只计算一次)。第二,到处都要处理这个反变量,这有点烦人。第三,这仍然是非常必要的
看待这个问题的另一种方法是从1
到n/2
的整数列表,并仅过滤n
的因子。这相当直接地转化为Haskell:
findFactors :: Integer -> [Integer]
findFactors num = filter (isAFactor num) [1..(num `div` 2)]
发现它与上述版本具有相同的性能特征可能会让人惊讶。Haskell不需要一次为整个列表分配多达
n/2的内存,它可以根据需要生成每个值。其他人已经很好地解释了您的代码,所以让我帮助您解码错误消息
Couldn't match expected type `[a] -> [Integer]'
against inferred type `IO ()'
In the expression:
putStrLn ("factorList is : " ++ show quotient) []
我错过了所有其他“表达中”的部分;他们只是显示出越来越多的e
Couldn't match expected type `[a] -> [Integer]'
against inferred type `IO ()'
In the expression:
putStrLn ("factorList is : " ++ show quotient) []
putStrLn :: String -> IO ()