Вам нужно FL.foldMap (FL.foldMap f) r
в вашем определении, чтобы вы сбросили Map
и Set
.
Однако в вашем экземпляре Functor
есть критическая ошибка;ваш fmap
является частичным.Он не определен в IdRMS
.
. Я предлагаю использовать -Wall
, чтобы компилятор предупреждал вас о таких проблемах.
Проблема сводится к тому, что вам необходимо представлять отношения сконечные и бесконечные области.IdRMS :: RelationRMS a a
уже может использоваться для представления некоторых отношений бесконечной области, он недостаточно силен для представления отношений, подобных fmap (\x -> [x]) IdRMS
.
Один из подходов заключается в использовании Map a (Set b)
для конечных отношений и a -> Set b
для бесконечных отношений.
data Relation a b where
Fin :: Map a (Set b) -> Relation a b
Inf :: (a -> Set b) -> Relation a b
image :: Relation a b -> a -> Set b
image (Fin f) a = M.findWithDefault (S.empty) a f
image (Inf f) a = f a
Это соответственно изменяет экземпляр категории:
instance Category Relation where
type Object Relation a = Ord a
id = Inf S.singleton
f . Fin g = Fin $ M.mapMaybe (nonEmptySet . concatMapSet (image f)) g
f . Inf g = Inf $ concatMapSet (image f) . g
nonEmptySet :: Set a -> Maybe (Set a)
nonEmptySet | S.null s = Nothing
| otherwise = Just s
concatMapSet :: Ord b => (a -> Set b) -> Set a -> Set b
concatMapSet f = S.unions . fmap f . S.toList
И теперь вы можете определить общий Functor
экземпляр:
instance Functor (Relation a) (Ord ⊢ (->)) Hask where
fmap (ConstrainedMorphism f) = ConstrainedMorphism $ \case -- using {-# LANGUAGE LambdaCase #-}
Fin g -> Fin $ fmap (S.map f) g
Inf g -> Inf $ fmap (S.map f) g
Но при определении экземпляра Foldable
возникает новая проблема:
instance Foldable (Relation a) (Ord ⊢ (->)) Hask where
foldMap (ConstrainedMorphism f) = ConstrainedMorphism $ \case
Fin g -> Prelude.foldMap (Prelude.foldMap f) g
Inf g -> -- uh oh...problem!
У нас есть f :: b -> m
и g :: a -> Set b
.Monoid m
дает нам append :: m -> m -> m
, и мы знаем Ord a
, но для генерации всех b
значений в изображении отношения нам нужны все возможные a
значения!
Один из способов попытаться спасти это - использовать Bounded
и Enum
в качестве дополнительных ограничений на домен отношения.Затем вы можете попытаться перечислить все возможные значения a
с помощью [minBound..maxBound]
(это может быть не каждое из перечисленных значений для всех типов; я не уверен, является ли это законом для Bounded
и Enum
).
instance (Enum a, Bounded a) => Foldable (Relation a) (Ord ⊢ (->)) Hask where
foldMap (ConstrainedMorphism f) = ConstrainedMorphism $ \case
Fin g -> Prelude.foldMap (Prelude.foldMap f) g
Inf g -> Prelude.foldMap (Prelude.foldMap f . g) [minBound .. maxBound]