测试带有负数的函数时出现类型错误
Type error when testing a function with a negative number
我正在关注 向您学习 Haskell 非常有用,我已经实施 take'
:
take' :: (Ord i, Num i) => i -> [a] -> [a]
take' n _
| n <= 0 = []
take' _ [] = []
take' n (x:xs) = x: take' (n-1) xs
测试功能时:
take' -2 [2]
我得到的不是空列表,而是这条消息:
Non type-variable argument in the constraint: Num (i -> [a] -> [a])
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall i a t.
(Num i, Num t, Num (i -> [a] -> [a]), Num ([t] -> i -> [a] -> [a]),
Ord i) =>
i -> [a] -> [a]
我按照建议在-
和2
之间添加了一个space,它导致了同样的错误:
*Main> take' - 2 [2]
<interactive>:78:1:
Non type-variable argument in the constraint: Num (i -> [a] -> [a])
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall i a t.
(Num i, Num t, Num (i -> [a] -> [a]), Num ([t] -> i -> [a] -> [a]),
Ord i) =>
i -> [a] -> [a]
正如评论中已经讨论的那样,这只是解析规则的问题。您的表达式 take' -2 [2]
确实看起来应该像您想要的那样表示 take' (-2) [2]
。可以说,它应该被这样解析。事实上 GHC 有一个扩展来实现这种行为:
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :set -XNegativeLiterals
Prelude> take -2 [2]
[]
然而,默认情况下,Haskell 总是首先尝试解析所有运算符,包括 -
,作为 中缀运算符 。在上面的表达式中,-
在左边和右边都有一些东西(尽管间距不一致,但它被忽略了),所以如果没有 -XNegativeLiterals
,它最终会被解析为 (take) - (2 [2])
,这意味着完全不同的东西。实际上,它完全是伪造的,正如错误消息以一种非常神秘的方式暗示的那样:它想要 Num (i -> [a] -> [a])
,即它发现您的代码需要将函数(即 take
)视为数字(即,作为减法运算符的参数)。
几乎总是当您看到包含对 Num (Some Compound Type)
的需求的错误时,这意味着在解析级别上已经完全出错了。
我正在关注 向您学习 Haskell 非常有用,我已经实施 take'
:
take' :: (Ord i, Num i) => i -> [a] -> [a]
take' n _
| n <= 0 = []
take' _ [] = []
take' n (x:xs) = x: take' (n-1) xs
测试功能时:
take' -2 [2]
我得到的不是空列表,而是这条消息:
Non type-variable argument in the constraint: Num (i -> [a] -> [a])
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall i a t.
(Num i, Num t, Num (i -> [a] -> [a]), Num ([t] -> i -> [a] -> [a]),
Ord i) =>
i -> [a] -> [a]
我按照建议在-
和2
之间添加了一个space,它导致了同样的错误:
*Main> take' - 2 [2]
<interactive>:78:1:
Non type-variable argument in the constraint: Num (i -> [a] -> [a])
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall i a t.
(Num i, Num t, Num (i -> [a] -> [a]), Num ([t] -> i -> [a] -> [a]),
Ord i) =>
i -> [a] -> [a]
正如评论中已经讨论的那样,这只是解析规则的问题。您的表达式 take' -2 [2]
确实看起来应该像您想要的那样表示 take' (-2) [2]
。可以说,它应该被这样解析。事实上 GHC 有一个扩展来实现这种行为:
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :set -XNegativeLiterals
Prelude> take -2 [2]
[]
然而,默认情况下,Haskell 总是首先尝试解析所有运算符,包括 -
,作为 中缀运算符 。在上面的表达式中,-
在左边和右边都有一些东西(尽管间距不一致,但它被忽略了),所以如果没有 -XNegativeLiterals
,它最终会被解析为 (take) - (2 [2])
,这意味着完全不同的东西。实际上,它完全是伪造的,正如错误消息以一种非常神秘的方式暗示的那样:它想要 Num (i -> [a] -> [a])
,即它发现您的代码需要将函数(即 take
)视为数字(即,作为减法运算符的参数)。
几乎总是当您看到包含对 Num (Some Compound Type)
的需求的错误时,这意味着在解析级别上已经完全出错了。