我定义了以下功能
let repl x n = [x | _ <- [1..n]]
它模仿内置的复制功能。
在尝试使用它时,我注意到一个奇怪的事情:repl 10 0
评估为[]
,而repl 10 -1
产生错误:
No instance for (Show (t10 -> [t0])) arising from a use of ‘print’
In a stmt of an interactive GHCi command: print it
另一方面,[1 .. 0]
和[1 .. -1]
评估为[]
而不会产生任何错误。
此外,[42 | _ <- [1 .. 0]]
和[42 | _ <- [1 .. -1]]
评估为[]
且没有错误。
那么为什么我的函数调用会导致显式替换不出错的错误?更重要的是,[1 .. 0]
和[1 .. -1]
之间的明显差异源自何处?
最后一个问题:我写的时候:
repl 42 -1
错误与repl 10 -1
完全相同,即它仍然包含(Show (t10 -> [t0]))
位。我期待它有像((Show (t42 -> [t0])))
这样的东西。这是什么10?
答案 0 :(得分:4)
其他答案指出您需要将-1
括在括号中。这是an odd corner of the Haskell 98 spec,意外地跳出来咬。如果不你不能在没有括号的情况下写下负数:-1 * 5
没问题。只是一元前缀运算符的优先级不高于二进制中缀运算符,因此-
经常被解析为后者。运算符周围的空格在Haskell中并不重要。
难以理解的类型类错误并没有帮助。顺便提一下,t10
和t0
只是编译器构成的占位符类型变量;我不认为它与您使用的实际数字文字有任何关系。非正式地,像Could not deduce (Num (a0 -> t))
这样的错误通常告诉我,一个函数适用于太少的参数。
或者,GHC 7.8中的(未记录的?)NegativeLiterals
语言扩展更改了-1
的含义以解决此问题。
> :set -XNegativeLiterals
> :t repl 10 -1
repl 10 -1 :: Num t => [t]
答案 1 :(得分:2)
您的问题中未包含 完整 错误消息,如果有,您会看到repl 10 -1
被解析为{{1这不是你想要的。
(repl 10) - (1)
会出现同样的错误。
通过仔细查看错误消息,您经常可以找到解析程序代码的线索。在你学习的同时,过度使用括号也没有坏处。
repl 10 +1
消息:
prog.hs:3:8: No instance for (Show (t1 -> [t0])) arising from a use of `print' Possible fix: add an instance declaration for (Show (t1 -> [t0])) In the expression: print (repl 10 - 1) In an equation for `main': main = print (repl 10 - 1) prog.hs:3:15: No instance for (Num t1) arising from a use of `repl' The type variable `t1' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there are several potential instances: instance Num Double -- Defined in `GHC.Float' instance Num Float -- Defined in `GHC.Float' instance Integral a => Num (GHC.Real.Ratio a) -- Defined in `GHC.Real' ...plus three others In the first argument of `(-)', namely `repl 10' --------- NB! In the first argument of `print', namely `(repl 10 - 1)' In the expression: print (repl 10 - 1) prog.hs:3:20: No instance for (Num t0) arising from the literal `10' The type variable `t0' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there are several potential instances: instance Num Double -- Defined in `GHC.Float' instance Num Float -- Defined in `GHC.Float' instance Integral a => Num (GHC.Real.Ratio a) -- Defined in `GHC.Real' ...plus three others In the first argument of `repl', namely `10' In the first argument of `(-)', namely `repl 10' --------- NB! In the first argument of `print', namely `(repl 10 - 1)' prog.hs:3:23: No instance for (Num (t1 -> [t0])) arising from a use of `-' Possible fix: add an instance declaration for (Num (t1 -> [t0])) In the first argument of `print', namely `(repl 10 - 1)' In the expression: print (repl 10 - 1) In an equation for `main': main = print (repl 10 - 1)
答案 2 :(得分:1)
你试过[1..(-1)]
吗?在Haskell中,你不能直接写出-1
这样的负数。你需要将它们放在括号中。原因是Haskell没有前缀一元运算符,因为Haskell中的运算符总是中缀。因此,-1
被解析为[operator (-)] [numeric 1]
而不是[numeric -1]
。
这是导致问题的原因。为避免此问题,必须将负数放在括号中。这可确保(-1)
被解析为[numeric -1]
。它是为数不多的能够在Haskell为新移民提供偏头痛的角落病例之一。