为什么在 Num 中没有定义(/)时,“1 / 2”会编译?
Why does "1 / 2" compile when there is no (/) defined in Num?
抱歉新手问题,但我真的不明白重载值:
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
(/)
定义在classFractional
中。是否有一些从 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 中的所有内容都是正确的,则将 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
Haskell 会将分子转换为 Fractional
并执行分数除法。如果你需要划分 Int
尝试使用中缀运算符 div
:
Prelude> x div y
看来您使用的是较新版本的 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
并且这种类型,因为它是多态的,所以当你评估 x/y
:
时,它是 specialized 到 Fractional a => a
Prelude> :t x/y
x/y :: Fractional a => a
因为 Num
是 Fractional
的超类,任何 Fractional
类型也是 Num
类型,因此特化了 x
和 y
到 Fractional a => a
是可能的。这与做类似的事情没有什么不同:
($) = id :: (a -> b) -> (a -> b)
函数 $
只是 id :: c -> c
的特化,其中 c = a -> b
。在你的情况下,你正在专门化一个受约束的类型,并且约束可以专门用 sub类 替换父 类 (即更一般的具有更具体的约束)所以 Fractional a => a
是 [=17 的专门化=].
当 ghci 必须输出结果时,它必须选择 /
运算符的实现 来计算结果,因此它必须 instantiate 将类型转换为具体类型。这是由 defaulting 完成的,因此执行的操作是 Double
实例的操作,但它们可以使用 default
声明进行更改。
请注意,默认值仅适用于 内置 类。引用上面的link:
Ambiguities in the class Num
are most common, so Haskell provides
another way to resolve them---with a default declaration:
default (t1 , ... , tn)
where n>=0
, and each ti
must be a type for which Num ti
holds. In
situations where an ambiguous type is discovered, an ambiguous type
variable, v
, is defaultable if:
v
appears only in constraints of the form C v
, where C
is a class, and
at least one of these classes is a numeric class, (that is, Num
or a subclass of Num
), and
- all of these classes are defined in the
Prelude
or a standard library (Figures 6.2--6.3, pages -- show the numeric classes, and
Figure 6.1, page , shows the classes defined in the Prelude.)
如果 x
和 y
的类型为 Num a => a
,则表示它们是多态的。它并不意味着“某种类型,你所知道的只是它是 Num
的一个实例”,而是“任何类型,只要它是 Num
的一个实例”。所以 x / y
然后有'任何类型,只要它是 Num
和 Fractional
的实例,因为 Fractional
是 [=13 的子 class =] 是 '任何类型,只要它是 Fractional
的实例,像 Rational
和 Double
这样的类型满足。
顺便说一句,1 / 2
照字面意思也将进行类型检查,原因与(比如)1 :: Double
和 2 :: Double
类型检查相同:1
in Haskell不限于整型,可用于任何数值类型。
抱歉新手问题,但我真的不明白重载值:
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
(/)
定义在classFractional
中。是否有一些从 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 中的所有内容都是正确的,则将 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
Haskell 会将分子转换为 Fractional
并执行分数除法。如果你需要划分 Int
尝试使用中缀运算符 div
:
Prelude> x div y
看来您使用的是较新版本的 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
并且这种类型,因为它是多态的,所以当你评估 x/y
:
Fractional a => a
Prelude> :t x/y
x/y :: Fractional a => a
因为 Num
是 Fractional
的超类,任何 Fractional
类型也是 Num
类型,因此特化了 x
和 y
到 Fractional a => a
是可能的。这与做类似的事情没有什么不同:
($) = id :: (a -> b) -> (a -> b)
函数 $
只是 id :: c -> c
的特化,其中 c = a -> b
。在你的情况下,你正在专门化一个受约束的类型,并且约束可以专门用 sub类 替换父 类 (即更一般的具有更具体的约束)所以 Fractional a => a
是 [=17 的专门化=].
当 ghci 必须输出结果时,它必须选择 /
运算符的实现 来计算结果,因此它必须 instantiate 将类型转换为具体类型。这是由 defaulting 完成的,因此执行的操作是 Double
实例的操作,但它们可以使用 default
声明进行更改。
请注意,默认值仅适用于 内置 类。引用上面的link:
Ambiguities in the class
Num
are most common, so Haskell provides another way to resolve them---with a default declaration:default (t1 , ... , tn)
where
n>=0
, and eachti
must be a type for whichNum ti
holds. In situations where an ambiguous type is discovered, an ambiguous type variable,v
, is defaultable if:
v
appears only in constraints of the formC v
, whereC
is a class, and at least one of these classes is a numeric class, (that is,Num
or a subclass ofNum
), and- all of these classes are defined in the
Prelude
or a standard library (Figures 6.2--6.3, pages -- show the numeric classes, and Figure 6.1, page , shows the classes defined in the Prelude.)
如果 x
和 y
的类型为 Num a => a
,则表示它们是多态的。它并不意味着“某种类型,你所知道的只是它是 Num
的一个实例”,而是“任何类型,只要它是 Num
的一个实例”。所以 x / y
然后有'任何类型,只要它是 Num
和 Fractional
的实例,因为 Fractional
是 [=13 的子 class =] 是 '任何类型,只要它是 Fractional
的实例,像 Rational
和 Double
这样的类型满足。
顺便说一句,1 / 2
照字面意思也将进行类型检查,原因与(比如)1 :: Double
和 2 :: Double
类型检查相同:1
in Haskell不限于整型,可用于任何数值类型。