2014-03-29 107 views
17

「某處」在「標準庫中或某些小而通用的包中,使其成爲相對無害的依賴」。這些monoid實例是否已經存在?

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) 

(這些情況下,應滿足幺法律 - 沒有刻意去證明它雖然合用的一個)

我這麼問是因爲我有一些使用了這兩項的和我不不想重新定義那些已經存在的東西。

+1

我發現這個討論並沒有說明這個庫是否存在,但似乎表明它沒有:http://www.haskell.org/pipermail/libraries/2012-April/ 017747.html – Emil

+7

'MApplicative'將完全符合monoid法則的定義:記住應用程序是_monoidal仿函數,在數學上! – leftaroundabout

+0

他們是強大鬆散monoidal函子,確切地說! – nimish

回答

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之間的遞歸。可能是一個問題。

1

我認爲這個問題的答案是「不」,這就是爲什麼它長期以來一直沒有正面答案。