Haskell 半群与幺半群实例中约束的差异
为什么幺半群实例需要(Ord a,Ord b)约束而半群实例不需要 这取决于Category.Constrained类还是GADT用于定义数据类型Haskell 半群与幺半群实例中约束的差异,haskell,category-abstractions,Haskell,Category Abstractions,为什么幺半群实例需要(Ord a,Ord b)约束而半群实例不需要 这取决于Category.Constrained类还是GADT用于定义数据类型 {-# LANGUAGE GADTs, TypeFamilies, ConstraintKinds, StandaloneDeriving #-} module Question3 where import Control.Category.Constrained as CC import Data.Set as S import Data.Ma
{-# 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 = (<>)
{-#语言GADT、类型族、约束种类、独立派生}
模块问题3在哪里
导入控件.Category.Constrained为CC
导入数据。设置为S
导入数据。映射为M
数据关系a b,其中
IdRMS::关系a
RMS::(Ord a,Ord b)=>地图a(集合b)->关系a b
派生实例(Show a,Show b)=>Show(relations a b)
RMS mp2`compRMS`RMS mp1
|M.null mp2 | | M.null mp1=RMS M.empty
|否则=RMS$M.foldrWithKey
(\k s acc->M.insert k(s.foldr)(\x acc2->case M.lookup x mp2 of
无->acc2
只需s2->S.union s2 acc2
)空的
)行政协调会
)M.empty mp1
实例类别关系,其中
类型对象关系M o=Ord o
id=IdRMS
()=compms
实例半群(关系a b),其中
RMS r1 RMS r2=RMS$M.foldrWithKey(\k s acc->M.insertWith s.union k s acc)r1 r2
实例(Ord a,Ord b)=>幺半群(关系a b),其中
mempty=RMS$M.empty
mappend=()
为什么幺半群实例需要(Ord a,Ord b)约束而半群实例不需要
尝试移除约束并让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
所以,是的。这当然与类别实例无关
半群
实例至少在概念上也需要Ord
,但是您已经在GADT中打包了它(除了在Id
情况下,它不需要,因为它很简单),因此不需要在实例头中提到约束
但是,对于
mempty
而言,您手头没有一个RelationMS
值,您可以从中读取(Ord a,Ord b)
约束。恰恰相反:您需要提供这些约束,因为您现在正试图结束这样一个GADT!这就是为什么Monoid
实例需要头部约束,而半群则不需要。这是正确的,但只是故事的一半()
也使用RMS
,但在这一点上,我们不需要Ord
约束。这是因为我们已经有了一个我们匹配的GADT模式。