5

我有数据类型:

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. 这实际上是一个幺半群吗?是否可以将其制成具有更好类型表示的类型。

4

1 回答 1

16

这被称为松散单曲面函子。我强烈建议你阅读这篇论文,它展示了 Applicatives 是一种松散的幺半群,你可以将你的类型重新定义为 anApplicative并获得一个等效的接口:

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 ()

请注意,tmappend并且tzero适用于所有Applicatives,而不仅仅是Stuff. 我链接的论文更详细地讨论了这个习语。

于 2013-05-29T14:23:26.737 回答