开发者

Inferring type class from operator

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.+)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜