如果数据结构是可折叠的,它是否是一个monoid?

时间:2018-08-13 09:08:24

标签: scala haskell functional-programming monads monoids

很明显,如果一个数据结构是一个monoid,它是可折叠的,但是可以确定地说一个数据结构是可折叠的,它是monoid吗?

https://en.wikibooks.org/wiki/Haskell/Foldable

如果数据结构是可折叠的,那么它是一个monoid吗?

2 个答案:

答案 0 :(得分:21)

您的主张“如果数据结构是Monoid,那么它就是Foldable”,这是不合理的。例如:

newtype ActionList a = ActionList (IO [a])

instance Monoid (ActionList a) where
    mempty = ActionList (return [])
    ActionList a `mappend` ActionList b = ActionList (liftA2 (++) a b)

这是一个非常好用的类人动物。但是,由于其所有值都在IO下,因此您无法从Foldable观察到它们中的任何一个。唯一的Foldable实例将是一个总是返回空的实例(从技术上讲,这是有效的,因为foldMap确实没有关于其有效性的任何定律,但是很难说这是一个好例子。具有直脸的实例)。

您要问的相反情况也不正确。例如:

data TwoThings a = TwoThings a a

这是可折叠的:

instance Foldable TwoThings where
    foldMap f (TwoThings x y) = f x <> f y

但是,如果以任何相关方式同时是FoldableMonoid的话,我希望以下同态定律成立:

foldMap f mempty = mempty
foldMap f (a <> b) = foldMap f a <> foldMap f b

我们无法使这些法律适用于TwoThings。请注意,foldMap (:[]) a的{​​{1}}始终具有两个元素。但是第二定律在左边有两个元素,在右边有四个元素。但是,dfeuer's answer显示,不需要法律来找到反例。

答案 1 :(得分:6)

这里有些Foldable(甚至是Traversable)也不希望成为Monoid的希望:

 
{-# language EmptyCase #-}

data F a

instance Foldable F where
  foldMap _ t = case t of
  -- or, = mempty
instance Traversable F where
  traverse _ t = case t of
  -- or, = pure $ case t of

instance Semigroup (F a) where
  -- the only option
  x <> _ = x

instance Monoid (F a) where
  mempty = ????