[英]Difference of constraints in Semigroup and Monoid instances
為什么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 = (<>)
這當然與類別實例無關。
Semigroup
實例至少在概念上也需要Ord
,但是你已經將它打包在GADT中(除了在Id
情況下,因為它是微不足道的,所以不需要它),所以沒有必要在實例中提到約束頭。
對於mempty
但是,你沒有 RelationMS
手頭價值,從中可以讀出(Ord a, Ord b)
的約束。 恰恰相反:你需要提供這些約束,因為你現在正試圖結束這樣的GADT! 這就是為什么Monoid
實例都需要在其頭部約束,但Semigroup
一個沒有。
為什么Monoid實例需要(Ord a,ord b)約束,而Semigroup實例卻沒有?
嘗試刪除約束並讓GHC告訴您原因。
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
|
RMS
需要Ord a
嗎? 你說:
RMS :: (Ord a, Ord b) => Map a (Set b) -> RelationMS a b
所以,是的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.