Haskell记录的Monoid,Applicative,Monad等的场分布

时间:2014-07-15 13:30:33

标签: haskell template-haskell

是否有一个大致包含以下内容的软件包:

给出记录:

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?泛型?)最适合实现它?

2 个答案:

答案 0 :(得分:4)

generic-deriving可以使用other作为幺半群部分,它提供了另一种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

在包中,还有FunctorTraversableFoldable的{​​{3}}个派生实例。

MonadApplicative可以使用类似于现有实例的泛型建模,如果更改类型;虽然,也许不是你喜欢的方式,但是,我认为,它们只会作为字段类型的产品仿函数而有意义,而不是你提出的那样。

答案 1 :(得分:0)

在真正的开源精神中,我编写了自己的库:

http://hackage.haskell.org/package/fieldwise

https://github.com/gracjan/fieldwise