2014-07-15 107 views
3

是否有做大致有以下包:Fieldwise銷售記錄

給定一個記錄:

data R = R { a :: TypeA, 
      b :: TypeB, 
      c :: TypeC } 

派生的提升紀錄:

data R_L f = R_L { a_L :: f TypeA, 
        b_L :: f TypeB, 
        c_L :: f TypeC } 

並提供了幾個實例和功能類似於:

instance (Monoid (f TypeA), Monoid (f TypeB), Monoid (f TypeC)) 
     => (Monoid (R_L f)) where 
    mempty = R_L mempty mempty mempty 
    mplus a b = ...fieldwise mplus... 

sequenceR :: (Monad m) => R_L m -> m R 
sequenceR = ... run fields, sum results ... 
sequenceRA :: (Applicative m) => R_L m -> m R 
sequenceRA x = R <$> a_L x <*> b_L x <*> c_L x 

和其他可能。有沒有提供這種功能的軟件包,如果沒有,哪種機制(TH?泛型?)最適合用來實現它?

+0

這幺情況下是沒有意義的,因爲'F'有種'* - > *'。可以使用'MonadPlus',這是你的意思嗎? – leftaroundabout

+0

編輯使Monoid實例稍微更清晰,但我也歡迎MonadPlus實例。 –

回答

4

幺半羣部分可能與generic-deriving,它提供了一個替代GMonoid,其中泛型自動實例。

{-# LANGUAGE DeriveGeneriC#-} 
{-# LANGUAGE FlexibleInstances, FlexibleContexts, DefaultSignatures #-} 

import Data.Monoid 
import qualified Generics.Deriving.Monoid as M 

data R_L f = R_L { a :: f [()], 
        b :: f String, 
        c :: f() } deriving (Generic) 

現在,你可以做到以下幾點:

*Main> let x = R_L (Just [()]) Nothing (Just()) `M.gmappenddefault` R_L (Just [()]) (Just "foo") (Just()) 
*Main> a x 
Just [(),()] 
*Main> b x 
Just "foo" 
*Main> c x 
Just() 

(我仍然搞清楚通用Show實例)

一個普通Monoid實例可以創建如下(思想,即可能會再次被稱爲樣板...):

instance (Monoid (f [()]), Monoid (f String), Monoid (f())) => Monoid (R_L f) where 
    mempty = M.memptydefault 
    mappend = M.mappenddefault 

在包中,Functor,TraversableFoldable也有other派生實例。

MonadApplicative也許可以用類似於現有的情況下仿製藥爲藍本,如果你改變了你的那種類型的;儘管可能並不符合你的喜好,因爲我認爲它們只會作爲字段類型的函子,而不是你所建議的。

+1

感謝通用派生提示,這應該是有用的。請注意,雖然你的建議並不是從R中派生出R_L,所以這對我來說是一個部分解決方案。 –

+0

哦,我很抱歉,我誤解/重讀了對_deriving_的使用。我仍然會留下答案,相信你會發現它有幫助。 – phg