在ghci中加载以下代码
\n{-# OPTIONS_GHC -Wall #-}\n\n\n--following gives a type error about the arg int not str\nbug :: String -> Int -> Int \nbug str int = num \n where num = str * 10 + int \n\n-- the following gives a type error about the arg str as expected \nworks :: String -> Int -> Int \nworks str int = str * 10 + int\nRun Code Online (Sandbox Code Playgroud)\n这给出了以下错误:
\n:reload\n[1 of 1] Compiling Main ( bugTI.hs, interpreted )\n\nbugTI.hs:6:16: error:\n \xe2\x80\xa2 Couldn't match type \xe2\x80\x98[Char]\xe2\x80\x99 with \xe2\x80\x98Int\xe2\x80\x99\n Expected: Int\n Actual: String\n \xe2\x80\xa2 In the expression: num\n In an equation for \xe2\x80\x98bug\xe2\x80\x99:\n bug str int\n = num\n where\n num = str * 10 + int\n |\n6 | bug str int = num \n | ^^^\n\nbugTI.hs:7:29: error:\n \xe2\x80\xa2 Couldn't match type \xe2\x80\x98Int\xe2\x80\x99 with \xe2\x80\x98[Char]\xe2\x80\x99\n Expected: String\n Actual: Int\n \xe2\x80\xa2 In the second argument of \xe2\x80\x98(+)\xe2\x80\x99, namely \xe2\x80\x98int\xe2\x80\x99\n In the expression: str * 10 + int\n In an equation for \xe2\x80\x98num\xe2\x80\x99: num = str * 10 + int\n |\n7 | where num = str * 10 + int \n | ^^^\n\nbugTI.hs:10:17: error:\n \xe2\x80\xa2 Couldn't match type \xe2\x80\x98[Char]\xe2\x80\x99 with \xe2\x80\x98Int\xe2\x80\x99\n Expected: Int\n Actual: String\n \xe2\x80\xa2 In the first argument of \xe2\x80\x98(*)\xe2\x80\x99, namely \xe2\x80\x98str\xe2\x80\x99\n In the first argument of \xe2\x80\x98(+)\xe2\x80\x99, namely \xe2\x80\x98str * 10\xe2\x80\x99\n In the expression: str * 10 + int\n |\n10 | works str int = str * 10 + int\n | ^^^\nFailed, no modules loaded.\nRun Code Online (Sandbox Code Playgroud)\n函数 bug 中第 7 行的错误表明它期望 int 是一个 String,这没有意义,因为它在算术表达式中。
\n函数中第 10 行的相应错误正常工作,表示它期望 str 是一个有意义的 Int。
\n在我看来,第 7 行的错误充其量是误导性的,最坏的情况(并且不太可能)是一个错误。有人可以解释为什么错误指向错误的变量吗?我想有一些我不明白的事情。
\n在我看来,第 7 行的错误充其量是误导性的,最坏的情况(并且不太可能)是一个错误。有人可以解释为什么错误指向错误的变量吗?我想有一些我不明白的事情。
(*) :: Num a => a -> a -> a、等函数没有什么“特殊”之处(+) :: Num a => a -> a -> a。这些只是Num类型类中定义的函数。
Num您也可以使其他类型成为类型类的成员,如果人们定义自己的类似数字的类型,则通常会发生这种情况。
因此,如果您愿意,您可以为Num类型String或一般列表定义一个实例。例如,您可以根据列表的长度对数字进行编码,从而对其进行算术运算。那么看起来会是这样的:
import Data.List(genericReplicate)
instance Num [a] where
(+) = (++)
(*) = (<*)
abs = id
signum = take 1
fromInteger = (`genericReplicate` undefined)
xs - ys = drop (length ys) xs
Run Code Online (Sandbox Code Playgroud)
我同意这作为 的实例没有多大意义Num,但它是实现这一点的可能方法之一。
Haskell 抱怨的是两个操作数和返回类型都需要具有相同的类型。事实上,在签名中,被用于两个操作数和返回类型。Num a => a -> a -> aa
由于类型签名int具有 as 类型Int,这意味着加法的两个操作数需要是Ints,因此 的结果str * 10应该是Int,这不是 的问题10,而是 的问题str。即使Num [a]成立,它仍然意味着这会出错,因为您不能将 anInt与 aDouble相乘,或者将 and 加Integer在一起Int。