我正在尝试制作一个非常简单的区域程序:
type Point = (Int, Int)
data Figure = Rect Point Point | Circ Point Int
area (Rect (x1,y1) (x2,y2)) = (x2 - x1) * (y1 - y2)
area (Circ _ r) = pi * r'^2 where r' = fromIntegral r
Run Code Online (Sandbox Code Playgroud)
当我手动输入时ghci,它没有错误并按预期工作.
但是,编译此程序会产生以下错误:
No instance for (Floating Int) arising from a use of `pi'
In the first argument of `(*)', namely `pi'
In the expression: pi * r' ^ 2
In an equation for `area':
area (Circ _ r)
= pi * r' ^ 2
where
r' = fromIntegral r
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?
始终使用类型签名.在这种情况下,您显然希望得到结果Double.一旦明确说明,编译器错误就会变得非常清楚.
目前尚不清楚错误的原因是:从第一个条款开始
area (Rect (x1,y1) (x2,y2)) = (x2 - x1) * (y1 - y2)
Run Code Online (Sandbox Code Playgroud)
编译器推断结果area具有(x2 - x1) * (y1 - y2)类型,x?与y?自身类型相同:Int.然后编译器检查它找到的第二个子句fromIntegral'.这可以产生任何数字类型,包括Int,所以这里没问题.因此推断乘法也是积分的.但这意味着pi需要Int同样,这显然是无稽之谈!
有了正确的签名,
area :: Figure -> Double
Run Code Online (Sandbox Code Playgroud)
编译器将在第一个子句停止,正确抱怨Int不匹配Double.你需要另一个fromIntegral.
函数的第一个等式具有返回类型Int,但第二个等式的返回类型为Floating a => a.现在编译器尝试统一awith Int,但Int不是Floating(如编译器告诉你的)实例,因此compailation失败并出现类型错误.
当您将这些行键入ghci时,它不会将第二个等式area视为函数定义的扩展,而是覆盖它.因此,如果您尝试area在ghci中使用Rect它将失败.
您没有在ghci中收到错误,因为您正在覆盖areafor 的定义Rect.
如果你这样做,你会得到错误:
let area (Rect (x1,y1) (x2,y2)) = (x2 - x1) * (y1 - y2); area (Circ _ r) = pi * r'^2 where r' = fromIntegral r
Run Code Online (Sandbox Code Playgroud)
这是你的代码(已-Wall启用):
Prelude> :set -Wall
Prelude> type Point = (Int, Int)
Prelude> data Figure = Rect Point Point | Circ Point Int
Prelude> let area (Rect (x1,y1) (x2,y2)) = (x2 - x1) * (y1 - y2)
<interactive>:5:5: Warning:
Pattern match(es) are non-exhaustive
In an equation for ‘area’: Patterns not matched: Circ _ _
Prelude> let area (Circ _ r) = pi * r'^2 where r' = fromIntegral r
<interactive>:6:5: Warning:
This binding for ‘area’ shadows the existing binding
defined at <interactive>:5:5
<interactive>:6:5: Warning:
Pattern match(es) are non-exhaustive
In an equation for ‘area’: Patterns not matched: Rect _ _
<interactive>:6:30: Warning:
Defaulting the following constraint(s) to type ‘Integer’
(Integral b0) arising from a use of ‘^’ at <interactive>:6:30
(Num b0) arising from the literal ‘2’ at <interactive>:6:31
In the second argument of ‘(*)’, namely ‘r' ^ 2’
In the expression: pi * r' ^ 2
In an equation for ‘area’:
area (Circ _ r)
= pi * r' ^ 2
where
r' = fromIntegral r
Run Code Online (Sandbox Code Playgroud)
一般来说,使用它总是一个好主意-Wall.