获取类型参数的标识?

时间:2019-05-12 13:47:05

标签: haskell monoids

我具有以下类型,希望成为Monoid类型类的实例。我不知道如何为身份设置参数化字段。使用参数化类型获取身份时是否有任何方法那个类型?

data Tree a=Leaf a | Node a (Tree a) (Tree a) |Empty deriving (Eq,Show)

instance Monoid Tree where
    mempty=Empty
    mappend a Empty=a
    mappend a b=Node (identity) x y

如您所见,我需要将简单字段设置为参数类型的标识。

示例

mappend::Tree Int
mappend (Leaf 1) (Leaf 2)=Node 0 (Leaf 1) (Leaf 2)

mappend::Tree []
mappend (Leaf [1,2])(Leaf [2,3])=Node [] (Leaf [1,2])(Leaf [2,3])

2 个答案:

答案 0 :(得分:9)

仅当a本身也是Monoid类型时,才会发生这种情况,因此我们可以这样写:

instance Monoid a => Monoid (Tree a) where
    mempty = Empty
    mappend Empty a = a
    mappend a Empty = a
    mappend a b = Node mempty a b

以上内容不适用于Int,因为Int不是Monoid。有两个非常受欢迎的候选项(ℕ,+,0)(ℕ,×,1)。但是,您可以使用Sum,它是前半体动物的表示。

最后一行正文中的mempty不是我们定义的mempty,而是mempty类型的a

话虽如此,如果您这样定义Monoid Tree,则意味着您考虑使用Node mempty (Node mempty a b) c == Node mempty a (Node mempty b c),因为这是 monoid定律所必需的。因此,deriving Eqmappend并不完全处于“ harmony ”。 mappend运算符(在数学中通常表示为)应满足条件∀a,b,c∈S:a⊕(b⊕c)=(a⊕ b)⊕c

您应该以不同的方式实现Eq自己,或者应该尝试为自己的半定式提出另一种结构。

答案 1 :(得分:2)

这不是答案,但是评论太久了。正如Willem Van Onsem所建议的那样,您的Monoid实例是非法的。我怀疑您可能想要两件事之一:

自由的岩浆

可以定义一种类型的自由岩浆

data Magma a = Branch (Magma a) (Magma a) | Leaf a | Empty
  deriving Show

这不是天生的类人动物,但假装有时是有用的。

instance Monoid (Magma a) where
  mempty = Empty
  mappend = Branch

-- For recent GHC, add this instance
instance Semigroup (Magma a) where
  (<>) = Branch

此功能可与折叠一起使用,以深入了解该折叠的结构。为了了解其工作原理,请比较将foldMap Leaf应用于[1..20]Data.Sequence.fromList [1..20]Data.Set.fromList [1..20]的结果。

一个(特别的)免费单子

考虑对树进行泛化,以允许内部节点中的叶子类型不同于叶子中的类型:

data Tree a b = Node a (Tree a b) (Tree a b) | Leaf b
  deriving (Show, Eq)

(这是定义的函子Tree a上的免费monad

data TreeF a b = NodeF a b b

但我们实际上并不需要深入了解这意味着什么。

Tree a monad的monad操作是一种“嫁接”,其中叶子被树替换。

instance Functor (Tree a) where
  fmap f (Leaf b) = Leaf (f b)
  fmap f (Node a l r) = Node a (fmap f l) (fmap f r)

instance Applicative (Tree a) where
  pure = Leaf
  (<*>) = ap
  liftA2 = liftM2

instance Monad (Tree a) where
  Leaf b >>= f = f b
  Node a l r >>= f = Node a (l >>= f) (r >>= f)

您可以认为>>=支持某种垂直附加,即树从其叶子向下生长。