bookkeeper: Anonymous records and overloaded labels

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

Please see for more information and examples.

[Skip to Readme]


Versions,,,,,,, 0.2.3, 0.2.4, 0.2.5, 0.2.5
Change log
Dependencies base (>=4.9 && <4.11), bookkeeper, data-default-class, markdown-unlit, type-level-sets [details]
License BSD-3-Clause
Copyright (c) Julian K. Arni
Author Julian K. Arni
Category Data Structures, Records
Home page
Bug tracker
Source repo head: git clone
Uploaded by aminb at 2017-12-17T21:08:05Z




Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Readme for bookkeeper-0.2.5

[back to package description]

Bookkeeper Build Status

Bookkeeper is a new Haskell library that uses the new OverloadedLabels feature of GHC 8 to provide a new take on datatypes and records:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE OverloadedLabels #-}
import Bookkeeper

jane :: Book '[ "name" :=> String, "age" :=> Int ]
jane = emptyBook
     & #name =: "Jane"
     & #age =: 30

-- >>> jane
-- Book {age = 30, name = "Jane"}
-- >>> jane ?: #name
-- "Jane"

It bears some similarities to Nikita Volkov's record library, but requires no Template Haskell.

Accesing a field that does not exist is a type error, made nicer with GHCs new custom type errors:

 -- >>> jane ?: #address
--   • The provided Book does not contain the field "address"
--     Book type:
--     '["age" ':-> Int, "name" ':-> String]

The order in which fields are inserted or appear in types does not matter. That is, in:

-- type A = Book '[ "field1" :=> Int,  "field2" :=> Bool]
-- type B = Book '[ "field2" :=> Bool, "field1" :=> Int ]

Types A and B are the same.

You can set, modify, or get fields. See the haddocks for more information.

main :: IO ()
main = return ()