简体   繁体   中英

Difference of constraints in Semigroup and Monoid instances

Why Monoid instance need (Ord a, Ord b) constraints while Semigroup instance doesn't?

Does this depend on the Category.Constrained class or the use of GADT to define the data type?

{-# LANGUAGE GADTs, TypeFamilies, ConstraintKinds, StandaloneDeriving #-}

module Question3 where

import Control.Category.Constrained as CC
import Data.Set as S
import Data.Map as M

data RelationMS a b where
  IdRMS :: RelationMS a a
  RMS :: (Ord a, Ord b) => Map a (Set b) -> RelationMS a b 
deriving instance (Show a, Show b) => Show (RelationMS a b)

RMS mp2 `compRMS` RMS mp1
  | M.null mp2 || M.null mp1 = RMS M.empty
  | otherwise = RMS $ M.foldrWithKey 
        (\k s acc -> M.insert k (S.foldr (\x acc2 -> case M.lookup x mp2 of
                                                    Nothing -> acc2
                                                    Just s2 -> S.union s2 acc2
                                         ) S.empty s
                                ) acc
        ) M.empty mp1

instance Category RelationMS where
    type Object RelationMS o = Ord o
    id = IdRMS
    (.) = compRMS

instance Semigroup (RelationMS a b) where 
    RMS r1 <> RMS r2 = RMS $ M.foldrWithKey (\k s acc -> M.insertWith S.union k s acc) r1  r2 

instance (Ord a, Ord b) => Monoid (RelationMS a b) where
    mempty = RMS $ M.empty
    mappend = (<>)

This certainly has nothing to do with the category instances.

The Semigroup instance does, at least conceptually, also require Ord , however you've already packed that in the GADT (except in the Id case, where it's not needed because it's trivial), so there's no need to mention the constraint in the instance head.

For mempty however, you don't have a RelationMS value at hand from which you could read out the (Ord a, Ord b) constraints. Quite the opposite: you need to provide these constraints, because you're now trying to wrap up such a GADT! That's why the Monoid instance needs the constraint in its head, but the Semigroup one doesn't.

Why Monoid instance need (Ord a, Ord b) constraints while Semigroup instance doesn't?

Try removing the constraint and having GHC tell you why.

ac.hs:33:14: error:
    • No instance for (Ord a) arising from a use of ‘RMS’
      Possible fix:
        add (Ord a) to the context of the instance declaration
    • In the expression: RMS $ M.empty
      In an equation for ‘mempty’: mempty = RMS $ M.empty
      In the instance declaration for ‘Monoid (RelationMS a b)’
   |
33 |     mempty = RMS $ M.empty
   |

So RMS requires Ord a ? You said:

  RMS :: (Ord a, Ord b) => Map a (Set b) -> RelationMS a b

So, yup.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM