如何/可以将此类型转换为Monoid实例

时间:2013-05-29 14:14:53

标签: haskell algebraic-data-types monoids

我有数据类型:

data Stuff s = Stuff { name :: s, idx :: Int } 

并希望通过以下实现将其变为幺半群:

tmappend :: Stuff s -> Stuff t -> Stuff (s,t) 
tmappend s1 s2 = Stuff (name s1, name s2) (idx s1 + idx s2)

tzero :: Stuff ()
tzero =  Stuff () 0

请注意,可以通过mconcat获得任意嵌套的元组。

但是tmappend目前正在违反mappend的类型签名。这实际上是一个幺半群吗?可以将它制作成具有更好类型表示的那个。

1 个答案:

答案 0 :(得分:16)

这被称为松散的monoidal仿函数。我强烈建议您阅读this paper,其中显示了Applicatives是一种松散的monoid类型,您可以将您的类型重新表述为Applicative并获得等效的界面:

instance Applicative Stuff where
    pure a = Stuff a 0
    (Stuff f m) <*> (Stuff x n) = Stuff (f x) (m + n)

tmappend :: (Applicative f) => f a -> f b -> f (a, b)
tmappend fa fb = (,) <$> fa <*> fb

tzero :: (Applicative f) => f ()
tzero = pure ()

请注意,tmappendtzero适用于所有Applicative,而不只是Stuff。我链接的论文更详细地讨论了这个习语。