How Haskell distinguishes the difference between possible instances of a class of type

Sorry if I use the wrong name for things. My question comes from comparing the syntax of Scala and Haskell. Consider:

class Monoid a where
  mempty :: a
  mappend :: a -> a -> a

instance Monoid Int where 
  mempty = 0
  mappend a b = a + b

sigma :: (Monoid a) => Int -> Int -> (Int -> Int) -> (Int -> a) -> a
sigma a b inc comp =
  if a > b then mempty else mappend (comp a) (sigma (inc a) b inc comp)

In Scala, it could be something like:

trait Monoid[A] {
  def mempty: A
  def mappend(a1: A, a2: A): A
}

class IntMonoid extends Monoid[Int] {
  def mempty = 0
  def mappend(a: Int, b: Int) = a + b
}

def sigma[A](a: Int, b: Int, inc: Int => Int, comp: Int => a)
            (implicit m: Monoid[A]): A =
  if (a > b) m.mempty else m.append(comp(a), sigma(inc(a), b, inc, comp))

Now Int can be a monoid with 0 and addition, but also with 1 and multiplication, so we can provide 2 types of classes, one for each implementation. In Scala, if both implementations are implicit within the scope and have the same priority, this will result in a compilation error. We can simply manually transfer the correct instance in this case, and the error will be resolved.

What is the Haskell equivalent for this situation? If there are two instances of Int that are Monoid, how to choose which implementation to use?

+4
2

Haskell newtype , Num ( Int) typeclass: Sum Product. , Sum , Product . :

newtype Sum a = Sum { getSum :: a }
        deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num)

instance Num a => Monoid (Sum a) where
        mempty = Sum 0
        Sum x `mappend` Sum y = Sum (x + y)

newtype Product a = Product { getProduct :: a }
        deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num)

instance Num a => Monoid (Product a) where
        mempty = Product 1
        Product x `mappend` Product y = Product (x * y)
+11

Haskell. , , .

, , , - , .

+4

Source: https://habr.com/ru/post/1539611/


All Articles