on master help sign in
add Tupleable typeclass documentation
commitdcac4debec5930e61722102dbc7001dc07ed163d authorAgentM <agentm@themactionfaction.com> dateThu 24 Aug 2017, 13:19 (9 years ago) parent63affe5
2 files changed+48−1
docs/new_datatypes.markdown+3−1 docs/tupleable.markdown+45
docs/new_datatypes.markdown+3−1
@@ -8,6 +8,8 @@ In addition, the Project:M36 runtime supports algebraic data types in the same v
88
99Project:M36 makes it easy to add any Haskell data type to the database. Any type which includes instances for a set of typeclasses can be supported.
1010
11+For storing Haskell record types as database tuples, see "[Converting data types to tuples](/docs/tupleable.markdown)."
12+
1113## Support for Runtime Types
1214
1315Use the ```tutd``` interpreter to create new type and data constructors with essentially the same syntax as in Haskell:
@@ -104,6 +106,6 @@ The essential ```Atomable``` typeclass functions are:
104106| ```toAtomType :: a -> AtomType``` | generate a database AtomType for a Haskell datatype |
105107| ```toDatabaseContextExpr :: a -> DatabaseContextExpr``` | generate a ```DatabaseContextExpr``` which can be executed against a database context in order to add the new type |
106108
107−In addition, basic Haskell data types like ```Int```, ```Double```, ```Text```, ```Day```, ```Bool```, ```UTCTime```, and ```ByteString``` already have Atomable instances ready-to-go. In addition, an ```Atomable``` instance is available for lists: ```Atomable a => [a]```, though one should be very careful not to use this in a common anti-pattern. Typically, it makes more sense to store one-to-many relationships as discrete relation variables; when storing them as lists, one gives up the various query capabilities and optimizations of the relational algebra.
109+In addition, basic Haskell data types like ```Int```, ```Double```, ```Text```, ```Day```, ```Bool```, ```UTCTime```, and l```ByteString``` already have Atomable instances ready-to-go. In addition, an ```Atomable``` instance is available for lists: ```Atomable a => [a]```, though one should be very careful not to use this in a common anti-pattern. Typically, it makes more sense to store one-to-many relationships as discrete relation variables; when storing them as lists, one gives up the various query capabilities and optimizations of the relational algebra.
108110
109111To be clear, these data types are not black boxes once stored in the database. These new types can be scanned and manipulated by Haskell scripts which can be created at runtime. For more information, read about [```AtomFunction```s](/docs/atomfunctions.markdown).
docs/tupleable.markdownnew file+45
@@ -0,0 +1,45 @@
1+# Marshaling Haskell Data Types to Database Tuples
2+
3+## Introduction
4+
5+Typical ORMs map certain data types to tuples within a relation variable. Because Project:M36 supports Haskell data types natively, any record data type which derives the ```Generic``` typeclass can be marshaled to a database tuple using the ```Tupleable``` typeclass. These marshaled database values can be operated on within the database using Haskell as well.
6+
7+## Setup
8+
9+Let's imagine we have a Haskell record type "Person" which we wish to map to a tuple in a relation variable called "person". Using ```GHC.Generics```, creating this mapping is trivial. Any record fields which are ```Atomable```, including algebraic data types, are supported.
10+
11+```haskell
12+import ProjectM36.Tupleable
13+
14+data Person = Person {
15+ name :: Text,
16+ employeeNumber :: Int,
17+ likesHorses :: Bool
18+}
19+deriving Generic
20+
21+instance Tupleable Person
22+```
23+
24+Now, ```Person``` values can be marshaled between the database and the client. The attribute names appearing in the Haskell data type will appear identically in the server with the same types.
25+
26+## Usage
27+
28+The ```Tupleable``` module includes the following functions:
29+
30+ * ```toInsertExpr :: (Tupleable a, Traversable t) => t a -> RelVarName -> Either RelationalError DatabaseContextExpr```
31+ * creates an ```Insert``` expression which can be used to insert a set of ```Tupleable``` values into the relation variable named by the ```RelVarName```
32+ * ```toAttributes :: a -> Attributes```
33+ * generates ```Attributes``` from a ```Tupleable``` value- can be used with ```undefined```, so an actual value is not necessary
34+ * ```toTuple :: a -> RelationTuple```
35+ * converts a ```Tupleable``` value to a tuple for use in queries
36+ * ```fromTuple :: RelationTuple -> Either RelationalError a```
37+ * converts a tuple to ```Tupleable``` value, unless there is an error such as a missing attribute
38+
39+For example usage, see the [Out of the Tarpit example](/examples/out_of_the_tarpit.hs).
40+
41+## Comparison to Other DBMSes
42+
43+The most annoying misfeature of the so-called object-relational model (ORM) is the data type impedance mismatch. This is especially egregious for Haskell clients which must contend with down-sampling the quality of Haskell data structures. For example, most DBMSes don't support algebraic data types, so the ORM can't represent them or it must represent them as binary or JSON blobs in the database which precludes such types from database-level type safety, constraints, and value queries.
44+
45+Project:M36 solves this mismatch by supporting algebraic data types as database-level values, Haskell scripting of database- and value-level server-side functions, and automatic and lossless marshaling of Haskell algebraic data types to values and tuples. Because the mapping between client data types and database-level data types is one-to-one, the mismatch is eliminated- any expression which could be evaluated against the data type on the client side can also be evaluated server-side.