什么八卦说,但我会添加一些想法。
这里的问题(不是问题!)是Haskell做出了一个折中:更具灵活性,代价是具体的错误报告。由于Haskell允许更多的事情,与其他主流语言相比,它有很多情况下不能报告错误,或者报告的错误比其他语言报告的更为抽象。
例如,假设你打算输入1 + 2
,但你发了胖,并输入了1 0 2
。以下是Python如何回应:
Python 2.7.2 (default, Oct 11 2012, 20:14:37)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1 0 2
File "<stdin>", line 1
1 0 2
^
SyntaxError: invalid syntax
简单:“您输入了错误的内容”。现在,Haskell:
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> 1 0 2
<interactive>:2:1:
No instance for (Num (a0 -> a1 -> t0)) arising from the literal `1'
Possible fix:
add an instance declaration for (Num (a0 -> a1 -> t0))
In the expression: 1
In the expression: 1 0 2
In an equation for `it': it = 1 0 2
<interactive>:2:3:
No instance for (Num a0) arising from the literal `0'
The type variable `a0' 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 `1', namely `0'
In the expression: 1 0 2
In an equation for `it': it = 1 0 2
<interactive>:2:5:
No instance for (Num a1) arising from the literal `2'
The type variable `a1' 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 second argument of `1', namely `2'
In the expression: 1 0 2
In an equation for `it': it = 1 0 2
在Python中,1 0 2
是语法错误。在Haskell中,1 0 2
意味着将函数1
应用于参数0
和2
。Haskell的错误信息不是“你不能这样做”,而是“你没有告诉我如何强制一个数字到一个双参数函数”(没有任何例子,对于Num (a0 -> a1 -> t0)
)。
就你而言,你设法编写了一些Haskell知道如何解释的东西,但意味着与你的意思非常不同。作为程序员,在这里做的最好的事情是使用描述你的意图的顶级类型声明,然后编译器可以检查这些。
最后一点:记住,你可以在Haskell做到这一点:
-- | Treat lists of numbers as numbers. Example:
--
-- >>> [1..3] * [2..5]
-- [2,3,4,5,4,6,8,10,6,9,12,15]
--
instance Num a => Num [a] where
xs + ys = [x + y | x <- xs, y <- ys]
xs * ys = [x * y | x <- xs, y <- ys]
xs - ys = [x - y | x <- xs, y <- ys]
negate xs = map negate xs
abs xs = map abs xs
signum xs = map signum xs
fromInteger x = [fromInteger x]
-- | Treat functions as numbers if they return numbers. The functions
-- must have the same argument type. Example:
--
-- >>> 1 0 2
-- 1
instance Num a => Num (r -> a) where
f + g = \r -> f r + g r
f * g = \r -> f r * g r
f - g = \r -> f r - g r
negate f = negate . f
abs f = abs . f
signum f = signum . f
fromInteger x = const (fromInteger x)
同样的事情可以用Integral
类来完成。
Glorious Glasgow Haskell编译系统,版本7.4.1 – user3309706