derive-0.1: Data/Derive/LazySet.hs
-- | A pseudo derivation. For each field in the data type, deriving
-- @LazySet@ generates a function like a record updator, but lazy.
-- This is very useful in certain situations to improve laziness
-- properties. Example:
--
-- > data Foo = Foo { x :: Int, y :: Int, z :: Int }
--
-- becomes:
--
-- > setX v f = Foo v (y f) (z f)
-- > setY v f = Foo (x f) v (z f)
-- > setZ v f = Foo (x f) (y f) v
module Data.Derive.LazySet(makeLazySet) where
import Language.Haskell.TH.All
import Data.Char
import Data.List
{-
data State = State {x :: Int, y :: Int}
==>
setX a0 b0 = State a0 (y b0)
setY a0 b0 = State (x b0) a0
-}
makeLazySet :: Derivation
makeLazySet = Derivation lazyset' "LazySet"
lazyset' dat = map f fields
where
fields = nub $ concatMap (\f -> map ((,) f) (ctorFields f)) (dataCtors dat)
f (ctor,field) = funN name [sclause [vr "a0", vr "b0"] (lK (ctorName ctor) body)]
where
name = "set" ++ toUpper (head field) : tail field
body = [ if fld == field then vr "a0" else l1 fld (vr "b0")
| fld <- ctorFields ctor ]