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.