2

Does the code below overload the operators from the Prelude Num and Fractional classes? It seems to me that is not possible to overload an operation in a class other than where the signature of the operation first appeared.

I have looked at a 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
Patrick Browne
  • 243
  • 1
  • 8
  • 2
    There are now two `(+)` functions: `(P.+)` and `(Numbers.+)`. But only for `Float` the `(Numbers.+)` function is defined, etc. But if you here use `x + y`, it will thus work with the one of the `Number` typeclass, since you imported `Prelude` in a `qualified` manner, it thus means that you need to use `(P.+)` to refer to the one of the `Num` typeclass. – Willem Van Onsem Jul 26 '22 at 11:02
  • 1
    You might like [a writeup I did on a previous question about how the module system namespacing and typeclass namespacing interact](https://stackoverflow.com/a/8331995/791604). – Daniel Wagner Jul 26 '22 at 22:32

2 Answers2

1

Does the code below overload the operators from the Prelude Num and Fractional classes? It seems to me that is not possible to overload an operation in a class other than where the signature of the operation first appeared.

Yes. You defined functions like (+), (-), and sqrt with the same name as in the Prelude. You imported the Prelude as qualified. This means that if you use 2 + 3, it will make use of the (+) function defined in the Number typeclass. If you want to refer to the one in the Prelude, you thus use (P.+), so x P.+ y.

Operators are just like functions, so x + y is syntactical sugar for (+) x y. It thus will follow the same rules to resolve a function name like sqrt. Since Prelude is a qualified import, this means that if you write sqrt, it will look for items in the scope, and the one defined in the Number typeclass is the only one in scope.

If you did not make a qualified import, you will need to use (Numbers.+) and (P.+) to disambiguate between the two. Or if you implement this without an explicit import of the Prelude with:

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

and thus disambiguate when you use these:

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

Except for the unary minus, there are thus no "builtin" operators. You can shadow any operator.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • 4
    Technically, I wouldn't call this "overloading". I'd call this "shadowing". And in this case it is not even really shadowing because the prelude is imported qualified. – Noughtmare Jul 26 '22 at 11:22
  • I am inclined to agree with @Noughtmare. I believe overloading involves using the same operator symbol with different argument types or different implementations of the operator.. But (+) and (P.+) seem to me to be two different symbols and they have the same implementation, – Patrick Browne Jul 26 '22 at 18:27
0

If we accept Bird's definition of overloaded functions:

"Overloaded functions are functions with the same name but different definitions."

Then I believe that the signatures for (+), (-), (*), sqrt, sqr in the Number class and their instance definitions do not fit Bird's definition of overloading.

Considering the infix functions (+), (-), and (*) they all occur in the Num class in the Prelude. Focusing on just (+) we have 3 distinct names or symbols in scope: (+), (P.+), and (Numbers.+) all with the same instance definition. This contradicts "same name" and "different definitions" from Bird. The sqrt function is a method from the Prelude Floating class. The sqr function is entirely local to the Number class it is not a method from the Num class in the Prelude.

Patrick Browne
  • 243
  • 1
  • 8