Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

file 77 lines (66 sloc) 2.213 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
-----------------------------------------------------------------------------
-- |
-- Module : AFRPMergeableRecord
-- Copyright : (c) Yale University, 2003
-- License : BSD-style (see the file LICENSE)
--
-- Maintainer : antony@apocalypse.org
-- Stability : provisional
-- Portability : non-portable (uses GHC extensions)
--
-- Framework for record merging.
--
-- Idea:
-- MergeableRecord is intended to be a super class for classes providing
-- update operations on records. The ADT induced by such a set of operations
-- can be considered a "mergeable record", which can be merged into larger
-- mergeable records essentially by function composition. Finalization turns
-- a mergeable record into a record.
--
-- Typical use:
-- Given
--
-- data Foo = Foo {l1 :: T1, l2 :: T2}
--
-- one define a mergeable record type (MR Foo) by the following instance:
--
-- instance MergeableRecord Foo where
-- mrDefault = Foo {l1 = v1_dflt, l2 = v2_dflt}
--
-- Typically, one would also provide definitions for setting the fields,
-- possibly (but not necessarily) overloaded:
--
-- instance HasL1 Foo where
-- setL1 v = mrMake (\foo -> foo {l1 = v})
--
-- Now Foo records can be created as follows:
--
-- let foo1 = setL1 v1
-- ...
-- let foo2 = setL2 v2 ~+~ foo1
-- ...
-- let foo<N> = setL1 vN ~+~ foo<N-1>
-- let fooFinal = mrFinalize foo<N>

module AFRPMergeableRecord (
    MergeableRecord(..),
    MR, -- Abstract
    mrMake,
    (~+~),
    mrMerge,
    mrFinalize
) where

class MergeableRecord a where
    mrDefault :: a


-- Type constructor for mergeable records.
newtype MergeableRecord a => MR a = MR (a -> a)


-- Construction of a mergeable record.
mrMake :: MergeableRecord a => (a -> a) -> MR a
mrMake f = (MR f)


-- Merge two mergeable records. Left "overrides" in case of conflict.
(~+~) :: MergeableRecord a => MR a -> MR a -> MR a
(MR f1) ~+~ (MR f2) = MR (f1 . f2)

mrMerge :: MergeableRecord a => MR a -> MR a -> MR a
mrMerge = (~+~)


-- Finalization: turn a mergeable record into a record.
mrFinalize :: MergeableRecord a => MR a -> a
mrFinalize (MR f) = f mrDefault
Something went wrong with that request. Please try again.