references: Selectors for reading and updating data.

[ bsd3, control, library ] [ Propose Tags ] [ Report a vulnerability ]

References are data accessors that can read, write or update the accessed infromation through their context. They are first-class values, can be passed in functions, transformed, combined. References generalize lenses, folds and traversals for haskell (see: https://hackage.haskell.org/package/lens).

References are more general than field selectors in traditional languages.

  • References are first-class values. If there is a struct in C, for example, with an int field fl, then fl can only be used as part of an expression. One can not generalize a function to take a field selector and transform the selected data or use it in other ways.

  • They can have different meanings, while field accessors can only represent data-level containment. They can express uncertain containment (like field selectors of C unions), different viewpoints of the same data, and other concepts.

There are two things that references can do but the previously mentioned access methods don't.

  • References can cooperate with monads, for example IO. This opens many new applications.

  • References can be added using the &+& operator, to create new lenses more easily.

Basic idea taken from the currently not maintained package https://hackage.haskell.org/package/yall.

An example use of the references (a logger application that spawns new threads to update a global log):

logger =
  (forever $ do
     log <- logChan ^? chan&logRecord    -- Extract the log record from the received log message
     thrId <- forkIO (do time <- getTime
                         ioref&lastLogTime != time $ logDB     -- Update the last logging time mutable log database
                         let logMsg = senderThread .- show     -- Transform the thread id to a string and
                                        $ loggingTime .= time  -- update the time
                                        $ log                  -- inside the log message
                         ioref&debugInfos !~ addLogEntry log $ logDB  -- update the table of log entries
                         mvar !- (+1) $ count )
     mvar !- (thrId:) $ updaters                               -- Record the spawned thread
    ) `catch` stopUpdaters updaters
  where stopUpdaters updaters ThreadKilled =
          mvar&traverse !| killThread $ updaters               -- Kill all spawned threads before stopping

There are a bunch of predefined references for datatypes included in standard libraries.

New references can be created in several ways:

  • From getter, setter and updater, using the reference function.

  • From getter and setter, using one of the simplified functions (lens, simplePartial, partial, ...).

  • Using the Data.Traversal instance on a datatype to generate a traversal of each element.

  • Using lenses from Control.Lens package. There are a lot of packages defining lenses, folds and traversals for various data structures, so it is very useful that all of them can simply be converted into a reference.

  • Generating references for newly defined datatypes using the makeReferences Template Haskell function.


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.2.0.0, 0.2.1.0, 0.2.1.1, 0.2.1.2, 0.3.0.0, 0.3.0.1, 0.3.1.0, 0.3.1.1, 0.3.2.0, 0.3.2.1, 0.3.2.2, 0.3.3.0, 0.3.3.1
Change log CHANGELOG.md
Dependencies array (>=0.5 && <1), base (>=4.9 && <5), containers (>=0.5 && <1), directory (>=1.2 && <2), either (>=4.3 && <6), filepath (>=1.3 && <2), instance-control (>=0.1 && <1), mtl (>=2.2 && <3), template-haskell (>=2.8 && <3), text (>=1.1 && <2), transformers (>=0.4 && <1), uniplate (>=1.6 && <2) [details]
License BSD-3-Clause
Copyright Boldizsar Nemeth, 2014
Author Boldizsar Nemeth
Maintainer nboldi@elte.hu
Category Control
Home page https://github.com/lazac/references
Source repo head: git clone git://github.com/lazac/references.git
Uploaded by lazac at 2017-11-28T00:57:57Z
Distributions
Reverse Dependencies 15 direct, 0 indirect [details]
Downloads 10606 total (15 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2017-11-28 [all 1 reports]

Readme for references-0.3.3.1

[back to package description]

References are data accessors that can read, write or update the accessed infromation through their context. They are first-class values, can be passed in functions, transformed, combined. References generalize lenses, folds and traversals for haskell (see: https://hackage.haskell.org/package/lens).

References are more general than field selectors in traditional languages.

  • References are first-class values. If there is a struct in C, for example, with an int field fl, then fl can only be used as part of an expression. One can not generalize a function to take a field selector and transform the selected data or use it in other ways.
  • They can have different meanings, while field accessors can only represent data-level containment. They can express uncertain containment (like field selectors of C unions), different viewpoints of the same data, and other concepts.

References are more potent than lenses, folds and traversals:

  • References can cooperate with monads, for example IO. This opens many new applications.
  • References can be added using the &+& operator, to create new lenses more easily.

Basic idea taken from the currently not maintained package https://hackage.haskell.org/package/yall.

An example use of the references (a logger application that spawns new threads to update a global log):

logger =
  (forever $ do
     log <- logChan ^? chan&logRecord    -- Extract the log record from the received log message
     thrId <- forkIO (do time <- getTime
                         ioref&lastLogTime != time $ logDB     -- Update the last logging time mutable log database
                         let logMsg = senderThread .- show     -- Transform the thread id to a string and
                                        $ loggingTime .= time  -- update the time
                                        $ log                  -- inside the log message
                         ioref&debugInfos !~ addLogEntry log $ logDB  -- update the table of log entries
                         mvar !- (+1) $ count )
     mvar !- (thrId:) $ updaters                               -- Record the spawned thread
    ) `catch` stopUpdaters updaters
  where stopUpdaters updaters ThreadKilled =    
          mvar&traverse !| killThread $ updaters               -- Kill all spawned threads before stopping

There are a number of predefined references for datatypes included in standard libraries.

New references can be created in several ways:

  • From getter, setter and updater, using the reference function.
  • From getter and setter, using one of the simplified functions (lens, simplePartial, partial, ...).
  • Using the Data.Traversal instance on a datatype to generate a traversal of each element.
  • Using lenses from Control.Lens package. There are a lot of packages defining lenses, folds and traversals for various data structures, so it is very useful that all of them can simply be converted into a reference.
  • Generating references for newly defined datatypes using the makeReferences Template Haskell function.

Hackage