如何定义Data.Foldable.Constrained的实例?

时间:2019-06-06 17:56:08

标签: haskell category-abstractions

我已经成功定义了类别,函子,半群,受约束的Monoid。现在,我陷入了Data.Foldable.Constrained。更准确地说,我似乎已经正确定义了不受约束的函数fldl和fldMp,但是我无法使它们被接受为Foldable.Constrained实例。 我的定义尝试已作为注释插入。

import

1 个答案:

答案 0 :(得分:2)

您需要在定义中使用FL.foldMap (FL.foldMap f) r,以便将Map折叠到Set上。

但是,您的Functor实例中存在严重错误;您的fmap是不完整的。未在IdRMS上定义。

我建议使用-Wall来让编译器警告您此类问题。

问题归结为您需要能够表示具有有限域和无限域的关系。 IdRMS :: RelationRMS a a已经可以用来表示无限域的 some 关系,但是它还不足以表示类似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 -> mg :: a -> Set bMonoid m给我们append :: m -> m -> m,我们知道Ord a,但是为了在关系的图像中生成所有b的值,我们需要所有可能的{{1 }}值!

您可以尝试解决此问题的一种方法是使用aBounded作为对该关系域的附加约束。然后,您可以尝试使用Enum枚举所有可能的a值(这可能不会列出所有类型的每个值;我不确定这是否适用于[minBound..maxBound]和{ {1}}。

Bounded