很难将Relation类型定义为Category类的实例

时间:2019-05-20 18:32:15

标签: haskell

我正在尝试将Relation a b定义为Category实例。在我看来,作曲家的定义明确,并遵守关联法。当涉及到ID时,我找不到正确的定义。我在做什么错了?

import Data.Map as M
import Data.Set as S
import Control.Category as Cat

newtype Relation a b = R (Map a (Set b)) deriving (Show, Eq)

-- instance Cat.Category Relation where
    -- id = 
    -- (.) = (°)

-- GHC.Base.id r1
-- > R (fromList [(10,fromList "abef"),(30,fromList "GRTXa")])

r1 = R $ M.fromList [(10,S.fromList "abfe"),(30,S.fromList "aXGRT")]
r2 = R $ M.fromList [('a',S.fromList [Just "Apple",Just "Ask"]),('b',S.fromList [Just "book",Just "brother"]),('T',S.fromList [Just "Table"]),('?',S.fromList [Just "Apple",Just "brother"])]

-- ex. r1 ° r2 = R (fromList [(10,fromList [Just "Apple",Just "Ask",Just "book",Just "brother"]),(30,fromList [Just "Apple",Just "Ask",Just "Table"])])


(°) :: (Ord a, Ord k, Ord b) => Relation a k -> Relation k b -> Relation a b   
R mp1 ° R mp2
  | M.null mp1 || M.null mp2 = R M.empty 
  | otherwise = R $ 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

1 个答案:

答案 0 :(得分:7)

Relation不能是Category的实例:

    luli在评论中指出,
  1. Relation仅表示有限关系(当视为对对时),但是无限集合上的恒等关系是无限的;

  2. 组合不是在所有类型上都定义,仅在Ord的实例上定义。

这是解决这些问题并使Relation成为Category实例的一种方法:

  1. 添加一个琐碎的元素来表示身份关系(这与使用Option从一个半群中形成一个半模像元的想法相同)
  2. 使其他“平凡的”关系带有Ord个实例。

这可以使用GADT完成。

{-# LANGUAGE GADTs #-}

data Relation a b where
  Id :: Relation a a
  R :: (Ord a, Ord b) => Map a (Set b) -> Relation a b

instance Category Relation where
  id = Id
  Id . r = r
  r . Id = r
  R r1 . R r2 = ...