Portability | unknown |
---|---|

Stability | experimental |

Maintainer | nonowarn@gmail.com |

Entiry based records. To use this module, you have to write LANGUGAGE pragma

{-# LANGUAGE TypeFamilies,TypeOperators,FlexibleContexts #-}

Or OPTIONS_GHC pragma if you are lazy.

{-# OPTIONS_GHC -fglasgow-exts #-}

- class Knows e (TypeOf e) r => Has e r
- type Field a = a ::: TyNil
- field :: a -> Field a
- fieldOf :: TypeOf a -> FieldOf a
- (^=) :: Knows e (TypeOf e) r => e -> TypeOf e -> r -> r
- (^.) :: Knows e (TypeOf e) r => e -> r -> TypeOf e
- (^:) :: Knows e (TypeOf e) r => e -> (TypeOf e -> TypeOf e) -> r -> r
- (^-) :: e -> TypeOf e -> FieldOf e
- class Contains (Labelled e v) r => Knows e v r | e r -> v where
- updl :: Knows e v r => e -> (v -> v) -> r -> r
- data Labelled lab a
- type :> lab a = Field (Labelled lab a)
- (.>) :: lab -> a -> lab :> a
- type family TypeOf a
- type family FieldOf a
- (&) :: Append a b => a -> b -> a :&: b
- type family a :&: b
- data a ::: b
- data TyNil
- class Contains e s

# Has constraint

class Knows e (TypeOf e) r => Has e r Source

Meaning of this constraint is "This record `s`

has a field of
entity `e`

." Here, I use the word "constraint" for class which
is useful on writing type signitures.

Holds `v == (e .^ (e ^= v $ s))`

where ```
e :: e; v ::
TypeOf e; s :: s
```

for all `e`

with `TypeOf e`

and `s`

.

Same as `Knows e (TypeOf e) s`

.

# Fields in Records

type Field a = a ::: TyNilSource

`Field a`

is a type list which contains only one element of
`a`

. And every field in the records should be this type.

If you concatenate fields with `(:&:)`

at type-level, `(&)`

at
value-level, it becomes a record can be manipulated by functions
in this module.

# Useful Operators

(^:) :: Knows e (TypeOf e) r => e -> (TypeOf e -> TypeOf e) -> r -> rSource

Modifies field of `e`

in `r`

with given function ```
TypeOf e ->
| TypeOf e
```

.

(^-) :: e -> TypeOf e -> FieldOf eSource

Creates field of `e`

with given value `TypeOf e`

.
Stealed from Chris Done's blog post: http://chrisdone.com/posts/2010-11-22-duck-typing-in-haskell.html

# Knows == Generalized version of Has

class Contains (Labelled e v) r => Knows e v r | e r -> v whereSource

Injects and projects a value of `v`

a corresponding field
in records `a`

along entity `e`

.

Holds `v == prjl e (injl e v r)`

.

updl :: Knows e v r => e -> (v -> v) -> r -> rSource

Updates a value of `v`

in a record `r`

using function of `v -> v`

.

## Labelled Fields

Represents labelled value.

Typeable2 Labelled | |

Bounded a => Bounded (Labelled lab a) | |

Eq a => Eq (Labelled lab a) | |

(Data lab, Data a) => Data (Labelled lab a) | |

Ord a => Ord (Labelled lab a) | |

Read a => Read (Labelled lab a) | |

Show a => Show (Labelled lab a) | |

Arbitrary a => Arbitrary (Labelled lab a) | |

CoArbitrary a => CoArbitrary (Labelled lab a) | |

Monoid a => Monoid (Labelled lab a) |

# Defining Entities and Records

`TypeOf a`

should indicate a type labelled by `a`

. When defining
entities, declare instance of this family. If you want `Foo`

entity points to `Int`

, you write

data Foo = Foo; type instance TypeOf Foo = Int

(&) :: Append a b => a -> b -> a :&: bSource

Concatenates between `Field`

s or records. Records are
concatenated rows. For example, Following expressions are
valid.

-- Concatenation of rows (i.e. record) field "string" & field True

-- Concatenation of records (field 'c' & field ()) & (field False & field "string")

-- ... And concatenations between a field and a record field () & (field False & field "string") (field 'c' & field ()) & field False

# Reading error messages easier

Cons a type onto type-list.

Typeable2 ::: | |

Contains e r => Contains e (::: h r) | |

Contains e (::: e r) | |

(Bounded a, Bounded b) => Bounded (::: a b) | |

(Eq a, Eq b) => Eq (::: a b) | |

(Data a, Data b) => Data (::: a b) | |

(Ord a, Ord b) => Ord (::: a b) | |

(Read a, Read b) => Read (::: a b) | |

(Show a, Show b) => Show (::: a b) | |

(Arbitrary a, Arbitrary b) => Arbitrary (::: a b) | |

(CoArbitrary a, CoArbitrary b) => CoArbitrary (::: a b) | |

(Monoid a, Monoid b) => Monoid (::: a b) | |

Append y b => Append (::: x y) b |

The empty type-list.