Alb*_*ani 2 haskell category-abstractions
为什么Monoid实例不需要(Ord a,Ord b)约束,而Semigroup实例却不需要?
这是否取决于Category.Constrained类或使用GADT定义数据类型?
{-# 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 = (<>)
Run Code Online (Sandbox Code Playgroud)
这当然与类别实例无关。
该Semigroup实例确实,至少在概念上,也需要Ord,但是你已经打包,在GADT(除了在Id情况下,它是没有必要的,因为它是琐碎的),所以没有必要提及的情况下头部约束。
对于mempty然而,你不要有一个RelationMS在手值,从中可以读出的(Ord a, Ord b)限制。恰恰相反:您需要提供这些约束,因为您现在正在尝试包装此类GADT!这就是为什么Monoid实例在其头部需要约束的原因,而实例Semigroup则不需要。