If I use the +
operator, Haskell automatically infers th开发者_Python百科e type class Num
:
> let add x y = x + y
> :t add
add :: Num a => a -> a -> a
Does this mean I cannot have multiple type classes with a +
operator?
You can't have multiple type classes defining +
in the same module (the same applies to any other function name of course - not just +
).
And if you import multiple modules which define +
(whether it be as part of a typeclass or not), you either need to hide +
when importing all but one of them, import all but one of them as qualified or always refer to +
qualified.
Note that +
is not so much an operator as it is a function which defaults to infix positioning. This means that it obeys the same kind of scoping rules as all other functions, and the same behaviour with typeclasses.
Specifically, a typeclass defines a number of functions that are polymorphic across all types that instantiate that particular typeclass. So given the definition of Num
as:
class (Eq a, Show a) => Num a where
(+) :: a -> a -> a
(*) :: a -> a -> a
(-) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
we can conclude that anything that includes a definition of Num
in its scope — such as anything importing Prelude
without qualification or exclusion of Num
— will already have a definition in scope for the function (+)
; which is an ordinary function with type signature a -> a -> a
, and a syntactic sugar tendency to be assumed infix, so that you'd write x + y
instead of + x y
.
In particular, all of this means that just as you can't have fmap
be a function defined both by the typeclass Functor
and by some other typeclass, you also can't have +
be defined both by Num
and by some other typeclass.
If you do want to define it elsewhere, you can always import the corresponding module qualified — however, the non-alphabetic function names that default to infix also end up really clumsy when you import them qualified. You'd end up writing things like 3 M.+ 4
instead of 3+4
.
I think the question is whether it's possible to have multi-class operators. This sounds like a misunderstanding of how type classes work. You may want to search for the type families extension, if you want to implement something like vector spaces, where the arguments have different types:
(.*) :: VectorSpace v => Scalar v -> v -> v
For a library using this approach see the vector-space package.
You can have multiple type classes with the +
operator, it's just that the Num
class implementation is imported implicitly via the Prelude. Either add the language extension
{-# LANGUAGE NoImplicitPrelude #-}
or add a line
import Prelude hiding ((+))
If you want a +
that includes two type classes, say Num
and A
, then you could create a new typeclass that encapsulates both,
import Prelude hiding (id, (.), (+))
import qualified Prelude
import qualified A
class GeneralPlus a where (+) :: a -> a -> a
instance Num a => GeneralPlus a where (+) = (Prelude.+)
instance A a => GeneralPlus a where (+) = (A.+)
精彩评论