haskell 这段代码是否重载了Prelude中的一些运算符?

xzv2uavs  于 2022-11-14  发布在  其他
关注(0)|答案(2)|浏览(153)

下面的代码是否重载了Prelude NumFractional类中的操作符?在我看来,除了操作签名首次出现的地方之外,不可能重载类中的操作。
我看过一个related question

module Numbers where
import qualified Prelude as P

    class Number a where
     (+), (-), (*) :: a -> a -> a
     sqr, sqrt:: a -> a
    
     
    instance Number P.Float where
     (+) a b =  a P.+ b
     (-) a b =  a P.- b
     (*) a b =  a P.* b
     sqrt a =  P.sqrt a
     sqr a = a P.* a
rqcrx0a6

rqcrx0a61#

下面的代码是否重载了Prelude Num和Fractional类中的运算符?在我看来,除了运算符首次出现的地方之外,不可能重载其他类中的运算符。

。您定义了与Prelude中名称相同的(+)(-)sqrt等函数。您将Prelude导入为qualified。这意味着如果您使用2 + 3,它将使用Number类型类中定义的(+)函数。如果要引用Prelude中的函数,则使用(P.+),因此x P.+ y

操作符就像函数一样,所以x + y(+) x y的语法糖。因此,它将遵循相同的规则来解析像sqrt这样的函数名。由于Preludequalified导入,这意味着如果您编写sqrt,它将在作用域中查找项。并且在Number类型类中定义的是范围中唯一的一个。
如果您没有进行 qualified 导入,则需要使用(Numbers.+)(P.+)来区分两者。或者,如果您在没有显式导入Prelude的情况下使用以下命令实现此操作:

module Numbers where

class Number a where
  (+), (-), (*) :: a -> a -> a
  sqr, sqrt:: a -> a

instance Number Prelude.Float where
 (+) a b =  a Prelude.+ b
 (-) a b =  a Prelude.- b
 (*) a b =  a Prelude.* b
 sqrt a =  Prelude.sqrt a
 sqr a = a Prelude.* a

从而在使用这些语句时消除歧义:

ghci> 1 Prelude.+ 2
3
ghci> 1 Numbers.+ 2 :: Float
3.0

除了 unary minus之外,没有“内置”运算符。你可以隐藏任何运算符。

vsnjm48y

vsnjm48y2#

如果我们接受Bird对重载函数的定义:

  • “重载函数是具有相同名称但定义不同的函数。"*

那么我相信Number类中的(+)(-)(*)sqrtsqr的签名和它们的示例定义符合Bird的重载定义。
考虑中缀函数(+)(-)(*),它们都出现在PreludeNum类中。仅关注(+),我们在作用域中有3个不同的名称或符号:(+)(P.+)、和(Numbers.+)都具有相同的示例定义。这与Bird中的“* 同名 ”和“ 不同的定义 *”相矛盾。sqrt函数是PreludeFloating类中的一个方法。sqr函数完全是Number类的本地函数,它不是PreludeNum类的方法。

相关问题