"某处"在标准库或某些软件包中,它们很小而且通用性足以使它成为一种相对无害的依赖性#34;。
import qualified Data.Map as M
import Data.Monoid
import Control.Applicative
newtype MMap k v = MMap {unMMap :: M.Map k v}
newtype MApplictive f a = MApplicative {unMApplicative :: f a}
-- M.unionWith f M.empty m = M.unionWith f m M.empty = m
-- f a (f b c) = f (f a b) c =>
-- M.unionWith f m1 (M.unionWith f m2 m3) =
-- M.unionWith f (M.unionWith f m1 m2) m3
instance (Ord k, Monoid v) => Monoid (MMap k v) where
mempty = MMap $ M.empty
mappend m1 m2 = MMap $ M.unionWith mappend (unMMap m1) (unMMap m2)
instance (Applicative f, Monoid a) => Monoid (MApplicative f a) where
mempty = MApplicative $ pure mempty
mappend f1 f2 = MApplicative $ liftA2 mappend (unMApplicative f1) (unMApplicative f2)
(这些实例应该满足幺半群法则 - 虽然没有为申请人证明这一点而烦恼)
我问,因为我对这两者都有用处,我不想重新定义已经存在的东西。
答案 0 :(得分:2)
这些实例存在于reducers,一个Edward Kmett包中。您的MApplicative
is known there as Ap
,MMap
is encoded through the Union
newtype。
答案 1 :(得分:1)
这样的东西?
class Functor f => Monoidal f where
fempty :: Monoid m => f m
fempty = fconcat []
fappend :: Monoid m => f m -> f m -> f m
fappend l r = fconcat [l, r]
fconcat :: (Foldable c, Monoid m) => c (f m) -> f m
fconcat = unMWrap $ foldMap MWrap
{-# MINIMAL fempty, fappend | fconcat #-}
-- Could just be Pointed instead of Applicative, but that's not in base
applicativeFEmpty :: (Applicative f, Monoid m) => f m
applicativeFEmpty = pure mempty
applicativeFAppend :: (Applicative f, Monoid m) => f m -> f m -> f m
applicativeFAppend = liftA2 mappend
applicativeFConcat :: (Applicative f, Monoid m, Foldable c) => c (f m) -> f m
applicativeFConcat = fmap mconcat . sequenceA . foldMap (:[])
newtype MonoidWrap f a = MWrap { unMWrap :: f a }
instance Monoidal f, Monoid m => Monoid (MonoidWrap f m) where
mempty = MWrap $ fempty . unMWrap
mappend l r = MWrap $ fappend (unMWap l) (unMWrap r)
mconcat = MWrap $ fconcat . map unMWrap
另外,基础中所有合适数据类型的Monoidal实例?它不会覆盖Data.Map.Map,这实际上是我对这种模式的最常见用法,但可以添加得足够简单。
不太确定mconcat和fconcat之间的递归。可能是个问题。
答案 2 :(得分:1)
我认为这个问题的答案是“不”,这就是为什么它长期没有得到肯定答案的原因。