on master help sign in
s/Identity/Result/ in readthedocs
commit6396ea1ceb2a531bb3e7544b3232240a1cec4298 authorOliver Charles <ollie@ocharles.org.uk> dateFri 18 Jun 2021, 20:49 (5 years ago) parent2487397
3 files changed+37−36
docs/concepts/dbtype.rst+18−17 docs/concepts/expr.rst+2−2 docs/tutorial.rst+17−17
docs/concepts/dbtype.rst+18−17
@@ -11,18 +11,19 @@ though most of these primitive ``DBType``\s should already be available.
1111Combining ``newtype`` and ``DBType``
1212------------------------------------
1313
14−You can define new instances of ``DBType`` by using Haskell "generalized newtype
15−deriving" strategy. This is useful when you have a common database type, but
16−need to interpret this type differently in different contexts. A very common
17−example here is with auto-incrementing ``id`` counters. In PostgreSQL, it's
18−common for a table to have a primary key that uses the ``serial`` type, which
19−means the key is an ``int8`` with a default value for ``INSERT``. In Rel8, we
20−could use ``Int64`` (as ``Int64`` is the ``DBType`` instance for ``int8``), but
21−we can be even clearer if we make a ``newtype`` for each *type* of id.
22−
23−If our database has users and orders, these tables might both have ids, but they
24−are clearly not meant to be treated as a common type. Instead, we can make these
25−types clearly different by writing::
14+You can define new instances of ``DBType`` by using Haskell "generalized
15+newtype deriving" strategy. This is useful when you have a common database
16+type, but need to interpret this type differently in different contexts. A very
17+common example here is with auto-incrementing ``id`` counters. In PostgreSQL,
18+it's common for a table to have a primary key that uses the ``serial`` type,
19+which means the key is an ``int8`` with a default value for ``INSERT``. In
20+Rel8, we could use ``Int64`` (as ``Int64`` is the ``DBType`` instance for
21+``int8``), but we can be even clearer if we make a ``newtype`` for each *type*
22+of id.
23+
24+If our database has users and orders, these tables might both have ids, but
25+they are clearly not meant to be treated as a common type. Instead, we can make
26+these types clearly different by writing::
2627
2728 newtype UserId = UserId { getUserId :: Int64 }
2829 deriving newtype DBType
@@ -57,8 +58,8 @@ In our PostgreSQL we have a few choices, but for now we'll assume that they are
5758stored as ``text`` values.
5859
5960In order to use this type in Rel8 queries, we need to write an instance of
60−``DBType`` for ``OrderStatus``. One approach is to use ``parseTypeInformation``,
61−which allows you to refine an existing ``DBType``::
61+``DBType`` for ``OrderStatus``. One approach is to use
62+``parseTypeInformation``, which allows you to refine an existing ``DBType``::
6263
6364 instance DBType OrderStatus where
6465 typeInformation = parseTypeInformation parser printer typeInformation
@@ -100,9 +101,9 @@ There usage is very similar to ``ReadShow`` - simply derive ``DBType via
100101JSONEncoded``, and Rel8 will use ``ToJSON`` and ``FromJSON`` instances (from
101102``aeson``) to serialize the given type.
102103
103−For example, a project might use event sourcing with a table of events. Each row
104−in this table is an event, but this event is stored as a JSON object. We can use
105−this type with Rel8 by writing::
104+For example, a project might use event sourcing with a table of events. Each
105+row in this table is an event, but this event is stored as a JSON object. We
106+can use this type with Rel8 by writing::
106107
107108 data Event = UserCreated UserCreatedData | OrderCreated OrderCreatedData
108109 deriving stock Generic
docs/concepts/expr.rst+2−2
@@ -58,7 +58,7 @@ Through the API reference documentation for Rel8, you might encounter the
5858``Sql`` type class. For example, if we look at the type of ``litExpr``, we
5959have::
6060
61− litExpr :: Sql DBType a => a -> Expr a
61+ litExpr :: Sql DBType a => a -> Expr a
6262
6363Here ``Sql DBType a`` means that ``a`` can either be literally a type that has
6464an instance of ``DBType`` (like ``UserId`` or ``Bool``), *or* that same type
@@ -69,6 +69,6 @@ Some functions work regardless of whether or not a value is null, and in these
6969cases you'll see ``Sql DBType a``. ``Sql`` can be used with any ``DBType``
7070subtype. For example, the type of ``div`` is::
7171
72− div :: Sql DBIntegral a => Expr a -> Expr a -> Expr a
72+ div :: Sql DBIntegral a => Expr a -> Expr a -> Expr a
7373
7474Which means ``div`` works on any ``DBIntegral a``, including ``Maybe a``.
docs/tutorial.rst+17−17
@@ -5,7 +5,7 @@ Getting Started
55
66In this section, we'll take a look at using Rel8 to work with a small database
77for Haskell packages. We'll take a look at idiomatic usage of Rel8, mapping
8−tables to Haskell, and then look at writing some simple queries.
8+tables to Haskell, and then look at writing some simple queries.
99
1010Before we get started, we'll be using the following language extensions and
1111imports throughout this guide::
@@ -70,7 +70,7 @@ Following these steps for ``author``, we have::
7070 { authorId :: Column f Int64
7171 , name :: Column f Text
7272 , url :: Column f (Maybe Text)
73− }
73+ }
7474 deriving stock (Generic)
7575 deriving anyclass (Rel8able)
7676
@@ -81,7 +81,7 @@ in our project, it would be too easy to accidentally mix them up and create
8181nonsensical joins. As Haskell programmers, we often solve this problem by
8282creating ``newtype`` wrappers, and we can also use this technique with Rel8::
8383
84− newtype AuthorId = AuthorId { toInt64 :: Int64 }
84+ newtype AuthorId = AuthorId { toInt64 :: Int64 }
8585 deriving newtype (DBEq, DBType, Eq, Show)
8686
8787Now we can write our final schema mapping. First, the ``author`` table::
@@ -90,7 +90,7 @@ Now we can write our final schema mapping. First, the ``author`` table::
9090 { authorId :: Column f AuthorId
9191 , authorName :: Column f Text
9292 , authorUrl :: Column f (Maybe Text)
93− }
93+ }
9494 deriving stock (Generic)
9595 deriving anyclass (Rel8able)
9696
@@ -99,7 +99,7 @@ And similarly, the ``project`` table::
9999 data Project f = Project
100100 { projectAuthorId :: Column f AuthorId
101101 , projectName :: Column f Text
102− }
102+ }
103103 deriving stock (Generic)
104104 deriving anyclass (Rel8able
105105
@@ -107,8 +107,8 @@ To show query results in this documentation, we'll also need ``Show`` instances:
107107Unfortunately these definitions look a bit scary, but they are essentially just
108108``deriving (Show)``::
109109
110− deriving stock instance f ~ Identity => Show (Author f)
111− deriving stock instance f ~ Identity => Show (Project f)
110+ deriving stock instance f ~ Result => Show (Author f)
111+ deriving stock instance f ~ Result => Show (Project f)
112112
113113These data types describe the structural mapping of the tables, but we also
114114need to specify a ``TableSchema`` for each table. A ``TableSchema`` contains
@@ -169,7 +169,7 @@ database heavy applications.
169169
170170In Rel8, ``SELECT`` statements are built using the ``Query`` monad. You can
171171think of this monad like the ordinary ``[]`` (List) monad - but this isn't
172−required knowledge.
172+required knowledge.
173173
174174To start, we'll look at one of the simplest queries possible - a basic ``SELECT
175175* FROM`` statement. To select all rows from a table, we use ``each``, and
@@ -193,17 +193,17 @@ expressions of type ``a``\".
193193To execute this ``Query``, we pass it to ``select``::
194194
195195 >>> :t select c (each projectSchema)
196− select c (each projectSchema) :: MonadIO m => m [Project Identity]
196+ select c (each projectSchema) :: MonadIO m => m [Project Result]
197197
198198When we ``select`` things containing ``Expr``s, Rel8 builds a new response
199−table with the ``Identity`` interpretation. This means you'll get back plain
199+table with the ``Result`` interpretation. This means you'll get back plain
200200Haskell values. Studying ``projectAuthorId`` again, we have::
201201
202− >>> let aProjectIdentity = undefined :: Project Identity
203− >>> :t projectAuthorId aProjectIdentity
204− projectAuthorId aProjectIdentity :: AuthorId
202+ >>> let aProjectResult = undefined :: Project Result
203+ >>> :t projectAuthorId aProjectResult
204+ projectAuthorId aProjectResult :: AuthorId
205205
206−Here ``Column Identity AuthorId`` reduces to just ``AuthorId``, with no
206+Here ``Column Result AuthorId`` reduces to just ``AuthorId``, with no
207207wrappping type at all.
208208
209209Putting this all together, we can run our first query::
@@ -343,8 +343,8 @@ focus on the /type/ of that query::
343343 where
344344
345345 >>> :t select c authorsAndProjects
346− select c authorsAndProjects
347− :: MonadIO m => m [(Author Identity, Project Identity)]
346+ select c authorsAndProjects
347+ :: MonadIO m => m [(Author Result, Project Result)]
348348
349349
350350Our query gives us a single list of pairs of authors and projects. However,
@@ -352,7 +352,7 @@ with our domain knowledge of the schema, this isn't a great type - what we'd
352352rather have is a list of pairs of authors and /lists/ of projects. That is,
353353what we'd like is::
354354
355− [(Author Identity, [Project Identity])]
355+ [(Author Result, [Project Result])]
356356
357357This would be a much better type! Rel8 can produce a query with this type by
358358simply wrapping the call to ``projectsForAuthor`` with either ``some`` or