为什么Data.Tree.Tree没有Monoid实例?

时间:2019-09-24 14:44:29

标签: haskell

我意识到答案可能是存在多个有效的此类实例(例如整数;求和,乘积...)。也许有人比这个答案更令人满意?

正如Joachim Breitner在此答案中How do you implement monoid interface for this tree in haskell?的出色解释,任何应用程序都有一个类半唯一实例:

mempty :: Applicative f => Monoid a => f a
mempty = pure mempty

mappend :: Applicative f => Monoid a => f a -> f a -> f a
mappend f g = mappend <$> f <*> g

所以我想知道为什么Data.Tree.Tree中的containers没有这样的实例?如果没有伴随的monoid实例,则相同的参数可以用于任何其他monad。在我看来,他们应该有这样的实例是很自然的。也许不是这样。我希望有人能启发我。

我认为另一个原因可能是我为树提议的实例不是“有用的”。我认为这与多重有效实例参数一样令人不满意。

2 个答案:

答案 0 :(得分:7)

我不知道为什么它不可用。但是,您提议的实例可以通过Ap新类型(它提供一个this.isGroupActive)永久使用。因此,如果您需要编写实例,即使使用裸instance (Applicative f, Monoid m) => Monoid (Ap f m)类型不存在该实例,也可以使用此实例。

答案 1 :(得分:1)

有多个有效实例。 Tree还支持“ zippy” Applicative及其对应的基于Ap的monoid:

instance Applicative Tree where
  pure a = let t = Node a (repeat t) in t
  liftA2 f (Node a as) (Node b bs) =
    Node (f a b) (zipWith (liftA2 f) as bs)

instance Semigroup a => Semigroup (Tree a) where
  Node a as <> Node b bs =
    Node (a <> b) (zipWith (<>) as bs)

instance Monoid a => Monoid (Tree a) where
  mempty = Node mempty (repeat mempty)

我不知道哪个实例(如果有的话)实际上会有用。


只是为了好玩,这是一个有点愚蠢的方法,它只是将构造函数放在底层的类半身像上:

instance Semigroup a => Semigroup (Tree a) where
  Node a as <> Node b bs = Node (a <> b) (as ++ bs)

instance Monoid a => Monoid (Tree a) where
  mempty = Node mempty []