很抱歉有新手问题,但我真的不明白重载值:
GHCi, version 7.8.3: http://www.haskell.org/ghc/ :? for help
Prelude> let x = 1
Prelude> let y = 2
x
和y
都有Num a => a
类型。但(/)
中没有定义Num
!那么为什么表达式x / y
类型检查?
Prelude> x / y
0.5
(/)
在课程Fractional
中定义。是否存在从Num
到Fractional
的隐式转换?
UPD :
所以,正如预期的那样,我得到的答案是人们声称x / y
a
专门针对Fractional a => a
。
我创建了自己的数字层次结构:
data MyInt = MyInt Integer deriving Show
data MyDouble = MyDouble Double deriving Show
class MyNum a where
(+#) :: a -> a -> a -- + renamed to +# to avoid collision with standard +
myFromInteger :: MyNum a => Integer -> a
class MyNum a => MyFractional a where
(/#) :: a -> a -> a
instance MyNum MyInt where
(MyInt a) +# (MyInt b) = MyInt (a + b)
myFromInteger i = MyInt i
instance MyNum MyDouble where
(MyDouble a) +# (MyDouble b) = MyDouble (a + b)
myFromInteger i = MyDouble (fromInteger i)
instance MyFractional MyDouble where
(MyDouble a) /# (MyDouble b) = MyDouble (a / b)
如果asnwers中的所有内容都为true,则Num
替换为MyNum
的类似代码也应该有效。但ghci报告错误:
Prelude> :load myint.hs
*Main> let x = myFromInteger 1
*Main> let y = myFromInteger 2
*Main> x /# y
<interactive>:14:1:
No instance for (MyFractional a0) arising from a use of `it'
The type variable `a0' is ambiguous
Note: there is a potential instance available:
instance MyFractional MyDouble -- Defined at myint.hs:19:10
In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it
答案 0 :(得分:6)
您似乎正在使用较新版本的ghci,默认情况下,该版本启用了NoMonomorphismRestriction
。在这种情况下,x
和y
确实有Num a => a
类型:
Prelude> :set -XNoMonomorphismRestriction
Prelude> let x = 1
Prelude> let y = 2
Prelude> :t x
x :: Num a => a
这种类型,因为它是多态的,在评估Fractional a => a
时专门到x/y
:
Prelude> :t x/y
x/y :: Fractional a => a
由于Num
是Fractional
的超类,因此任何Fractional
类型也是Num
类型,因此专门针对x
和{{1}的类型} y
是可能的。这与做类似的事情没有什么不同:
Fractional a => a
函数($) = id :: (a -> b) -> (a -> b)
只是$
id :: c -> c
的特化。在您的情况下,您正在专门化一个约束类型,并且约束可以通过子类替换父类(即更一般地使用更具体的约束),因此c = a -> b
是Fractional a => a
的特化。
当ghci必须输出结果时,必须选择 Num a => a
运算符的 来计算结果,因此它必须实例化键入具体类型。这是由defaulting完成的,因此执行的操作是/
实例的操作,但可以使用Double
声明更改它们。
请注意,默认只适用于内置类。引用上面的链接:
类
default
中的歧义最常见,因此Haskell提供 另一种解决方法 - 使用默认声明:Num
其中
default (t1 , ... , tn)
,每个n>=0
必须是ti
所持有的类型。在 发现模糊类型的情况,模糊类型 变量Num ti
在以下情况下是可以违约的:
v
仅出现在v
形式的约束中,其中C v
是一个类,并且 这些类中至少有一个是数字类(即C
或Num
的子类),- 所有这些类都在
Num
或标准库中定义(图6.2--6.3,页面 - 显示数字类,以及 图6.1,页面显示了Prelude中定义的类。)
答案 1 :(得分:0)
如果x
和y
的类型为Num a => a
,则表示它们具有多态性。它并不代表某种类型,你所知道的只是它是Num
&#39;的一个实例,但是&#39;任何类型,只要它& #39;是Num
&#39;的一个实例。因此,x / y
只要有Num
和Fractional
的实例,就会有任何类型,因为Fractional
是一个子类Num
是任何类型,只要它是Fractional
的实例,其类型如Rational
和Double
就满足。
顺便说一句,1 / 2
字面意思也会进行类型检查,原因与(例如)1 :: Double
和2 :: Double
类型检查:Haskell中的1
不是&# 39; t限于整数类型,但可用于任何数字类型。
答案 2 :(得分:-1)
Haskell会将分子转换为Fractional
并执行分数除法。如果您需要划分Int
,请尝试使用中缀运算符div
:
Prelude> x div y