@@ -10,9 +10,9 @@ SQL intentionally differentiates NULL from all other values. NULL is not an inte
1010
1111```
1212postgres=# select NULL = NULL;
13− ?column?
13+ ?column?
1414----------
15−
15+
1616(1 row)
1717```
1818
@@ -68,7 +68,7 @@ postgres=# select * from x where a=a;
6868Example 3: Return all rows where b is from a list of NULL.
6969```
7070postgres=# select * from x where b = any(NULL);
71− a | b
71+ a | b
7272---+---
7373(0 rows)
7474```
@@ -101,7 +101,7 @@ postgres=# select * from x where exists (SELECT * FROM x as y where (a,b) = (y.a
101101(3 rows)
102102````
103103
104−All of the above query examples conform to the SQL standard with regards to NULL handling.
104+All of the above query examples conform to the SQL standard with regards to NULL handling.
105105
106106
107107## Inconsistencies Leading to Errors
@@ -110,8 +110,8 @@ If the difference between NULL handling in ```ANY``` versus ```EXISTS``` didn't
110110
111111Example 7: Aggregate a sum over a in x where one a value is NULL.
112112```
113−postgres=# select sum(a) from x;
114− sum
113+postgres=# select sum(a) from x;
114+ sum
115115-----
116116 3
117117(1 row)
@@ -119,20 +119,20 @@ postgres=# select sum(a) from x;
119119Example 8: Aggregate a sum over two NULLs.
120120```
121121postgres=# select sum(a) from (values (NULL::int),(NULL)) as y(a); --sum of only NULLs is NULL
122− sum
122+ sum
123123-----
124−
124+
125125(1 row)
126126```
127127Example 9: Count the number of a values in x. Count the number of rows in x.
128128```
129129postgres=# select count(a) from x;
130− count
130+ count
131131-------
132132 2
133133(1 row)
134134postgres=# select count(*) from x;
135− count
135+ count
136136-------
137137 3
138138(1 row)
@@ -142,17 +142,17 @@ Example 10: Aggregate the sum of an empty table.
142142postgres=# create table z(a int);
143143CREATE TABLE
144144postgres=# select sum(a) from z; -- sum of empty table is NULL
145− sum
145+ sum
146146-----
147−
147+
148148(1 row)
149149```
150150Example 11: NULL multipled by zero plus three.
151151```
152152postgres=# select 0*NULL + 3;
153− ?column?
153+ ?column?
154154----------
155−
155+
156156(1 row)
157157```
158158
@@ -161,9 +161,9 @@ This logic follows into arrays:
161161Example 12: Is NULL equal to any element in the array?
162162```
163163postgres=# select NULL = ANY(array[1,2,3,NULL]);
164− ?column?
164+ ?column?
165165----------
166−
166+
167167(1 row)
168168```
169169
@@ -172,13 +172,13 @@ and row-valued expressions:
172172Example 13: Is the (NULL,1) tuple equal to NULL? Is it not equal to NULL?
173173```
174174postgres=# select (NULL,1) is null;
175− ?column?
175+ ?column?
176176----------
177177 f
178178(1 row)
179179
180180postgres=# select (NULL,1) is not null;
181− ?column?
181+ ?column?
182182----------
183183 f
184184(1 row)
@@ -193,12 +193,12 @@ SQL does not enforce the relational model constraint that rows (tuples) be uniqu
193193Example 14: Create multiple NULLs in a result set.
194194```
195195postgres=# select * from (values (34),(50),(NULL),(NULL)) as employee_age(val);
196− val
196+ val
197197-----
198198 34
199199 50
200−
201−
200+
201+
202202(4 rows)
203203```
204204
@@ -222,14 +222,14 @@ postgres=# insert into z(a,b) values (2,'two'),(NULL,NULL) returning a,b;
222222 a | b
223223---+-----
224224 2 | two
225− |
225+ |
226226(2 rows)
227227postgres=# select x.a as xa,x.b as xb,z.a as za,z.b as zb from x left join z on x.a is not distinct from z.a;
228228 xa | xb | za | zb
229229----+-------+----+-----
230− 1 | one | |
230+ 1 | one | |
231231 2 | two | 2 | two
232− | three | |
232+ | three | |
233233(3 rows)
234234
235235```
@@ -306,7 +306,7 @@ and some examples values:
306306* ```PreciseAge 25```
307307* ```NotApplicable```
308308* ```ApproximateAge 30 40``` approximately between 30-40 years old
309−
309+
310310Already, we can see that this single data type can pack far more useful information than any combination of an integer and NULL.
311311
312312### Algebraic Data Types In SQL
@@ -317,8 +317,8 @@ An algebraic data type may be emulated in SQL, albeit in a convoluted fashion an
317317postgres=# create type age_type as enum ('precise_age', 'forgot_to_ask', 'refused_to_disclose', 'not_applicable', 'approximate_age');
318318CREATE TYPE
319319
320−postgres=# create table hospital_patient(name text not null,
321− age age_type not null,
320+postgres=# create table hospital_patient(name text not null,
321+ age age_type not null,
322322 precise_age int,
323323 approximate_age int[2]);
324324postgres=# insert into hospital_patient(name,age,precise_age,approximate_age) values ('Bob','approximate_age',NULL,array[30,40]);
@@ -342,6 +342,38 @@ But all we have really done is add even more NULLs. Retrieving a sensible value
342342
343343### Algebraic Data Types In Project:M36
344344
345+## Runtime Types
346+
347+Project:M36 supports management of new algebraic data types at runtime. These types are associated with transactions and can changed over time whereas primitive Atoms cannot be changed.
348+d
349+```
350+TutorialD (master): data Age = PreciseAge Int | ForgotToAsk | RefusedToDisclose | NotApplicable | ApproximateAge Int Int
351+TutorialD (master): :showexpr relation{tuple{name "Steve", age ApproximateAge 20 30}, tuple{name "Bob", age RefusedToDisclose}, tuple {name "Initech Corp.", age NotApplicable}}
352+┌────────────────────┬───────────────┐
353+│age::Age │name::Text │
354+├────────────────────┼───────────────┤
355+│ApproximateAge 20 30│"Steve" │
356+│NotApplicable │"Initech Corp."│
357+│RefusedToDisclose │"Bob" │
358+└────────────────────┴───────────────┘
359+```
360+
361+Note that the two values which would normally be rendered as NULL in SQL are indeed proper values and can be distinguished. Three-valued logic makes no appearance. The type constructors can also have arguments:
362+
363+```
364+TutorialD (master): data Tree a = Node a (Tree a) (Tree a) | EmptyNode
365+TutorialD (master): :showexpr relation{tuple{family "Stevenson", familytree Node "Jim" (Node "Cindy" EmptyNode EmptyNode) (Node "Mike" EmptyNode EmptyNode)}}
366+┌────────────┬───────────────────────────────────────────────────────────────────────────────┐
367+│family::Text│familytree::Tree (a::Text) │
368+├────────────┼───────────────────────────────────────────────────────────────────────────────┤
369+│"Stevenson" │Node "Jim" (Node "Cindy" EmptyNode EmptyNode) (Node "Mike" EmptyNode EmptyNode)│
370+└────────────┴───────────────────────────────────────────────────────────────────────────────┘
371+```
372+
373+Algebraic data types in SQL are effectively impossible.
374+
375+## Haskell Types
376+
345377Any Haskell data type can be turned into a value (called an "atom") in Project:M36. The following example illustrates:
346378
347379```haskell
@@ -365,7 +397,7 @@ data AgeType = PreciseAge Int |
365397 NotApplicable |
366398 ApproximateAge Int Int
367399 deriving (Eq,Show,Read,Hashable,Binary,Typeable,NFData,Generic)
368−
400+
369401instance Atomable AgeType
370402
371403failFastMaybe :: (Show a) => Maybe a -> IO ()
@@ -378,15 +410,15 @@ failFastEither (Right val) = return val
378410
379411ageAtomType :: AtomType
380412ageAtomType = atomTypeForProxy (Proxy :: Proxy AgeType)
381−
413+
382414runExample :: IO ()
383415runExample = do
384416 let bob_relation_attrs = attributesFromList [Attribute "name" stringAtomType,
385417 Attribute "age" ageAtomType]
386418 relvar_name = "hospital_patient"
387− age_value_in = ApproximateAge 30 40
388− bob_relation_err = mkRelationFromList
389− bob_relation_attrs
419+ age_value_in = ApproximateAge 30 40
420+ bob_relation_err = mkRelationFromList
421+ bob_relation_attrs
390422 [[Atom ("Bob"::Text), Atom age_value_in]]
391423
392424 connerr <- connectProjectM36 (InProcessConnectionInfo NoPersistence)
@@ -427,7 +459,3 @@ Regardless, modeling the fact that some information may be missing is valuable,
427459Date, C.J. Darwen, Hugh. [Database Explorations: Essays on the Third Manifesto and Related Topics](http://bookstore.trafford.com/Products/SKU-000177853/Database-Explorations.aspx) chapters 23-29
428460
429461Date, C.J. [Database in Depth](http://bookstore.trafford.com/Products/SKU-000177853/Database-Explorations.aspx) pages 53-55
430−
431−
432−
433−