on master help sign in
Document Rel8.Table.Maybe
commite9796d869da1280a5a33cf8bb14aa3cbb2e99a69 authorOllie Charles <ollie@ocharles.org.uk> dateTue 23 Mar 2021, 16:12 (6 years ago) parentbfda1da
1 file changed+24
src/Rel8/Table/Maybe.hs+24
src/Rel8/Table/Maybe.hs+24
@@ -63,6 +63,14 @@ import Data.Functor.Apply ( Apply, (<.>) )
6363import Data.Functor.Bind ( Bind, (>>-) )
6464
6565
66+-- | @MaybeTable t@ is the table @t@, but as the result of an outer join. If
67+-- the outer join fails to match any rows, this is essentialy @Nothing@, and if
68+-- the outer join does match rows, this is like @Just@. Unfortunately, SQL
69+-- makes it impossible to distinguish whether or not an outer join matched any
70+-- rows based generally on the row contents - if you were to join a row
71+-- entirely of nulls, you can't distinguish if you matched an all null row, or
72+-- if the match failed. For this reason @MaybeTable@ contains an extra field -
73+-- a "nullTag" - to track whether or not the outer join produced any rows.
6674type MaybeTable :: Type -> Type
6775data MaybeTable a = MaybeTable
6876 { tag :: Expr (Maybe MaybeTag)
@@ -75,6 +83,8 @@ instance Apply MaybeTable where
7583 MaybeTable tag f <.> MaybeTable tag' a = MaybeTable (tag <> tag') (f a)
7684
7785
86+-- | Has the same behavior as the @Applicative@ instance for @Maybe@. See also:
87+-- 'traverseMaybeTable'.
7888instance Applicative MaybeTable where
7989 (<*>) = (<.>)
8090 pure = justTable
@@ -85,6 +95,8 @@ instance Bind MaybeTable where
8595 MaybeTable tag' b -> MaybeTable (tag <> tag') b
8696
8797
98+-- | Has the same behavior as the @Monad@ instance for @Maybe@. See also:
99+-- 'bindMaybeTable'.
88100instance Monad MaybeTable where
89101 (>>=) = (>>-)
90102
@@ -152,26 +164,38 @@ instance
152164 ) => Recontextualize from to (MaybeTable a) (MaybeTable b)
153165
154166
167+-- | Check if a @MaybeTable@ is absent of any row.. Like 'isNothing'.
155168isNothingTable :: MaybeTable a -> Expr Bool
156169isNothingTable (MaybeTable tag _) = isNull tag
157170
158171
172+-- | Check if a @MaybeTable@ contains a row. Like 'isJust'.
159173isJustTable :: MaybeTable a -> Expr Bool
160174isJustTable (MaybeTable tag _) = isNonNull tag
161175
162176
177+-- | Perform case analysis on a 'MaybeTable'. Like 'maybe'.
163178maybeTable :: Table DB b => b -> (a -> b) -> MaybeTable a -> b
164179maybeTable b f ma@(MaybeTable _ a) = bool (f a) b (isNothingTable ma)
165180
166181
182+-- | The null table. Like 'Nothing'.
167183nothingTable :: Table DB a => MaybeTable a
168184nothingTable = MaybeTable null undefined
169185
170186
187+-- | Lift any table into 'MaybeTable'. Like 'Just'. Note you can also use
188+-- 'pure'.
171189justTable :: a -> MaybeTable a
172190justTable = MaybeTable (nullify (litExpr IsJust))
173191
174192
193+-- | Project a single expression out of a 'MaybeTable'. You can think of this
194+-- operator like the '$' operator, but it also has the ability to return
195+-- @null@.
196+--
197+-- >>> select c $ fmap (fst $?) (optional (values [lit (True, False)]))
198+-- [Just True]
175199($?) :: forall a b db. (DBType db, Nullabilizes db b)
176200 => (a -> Expr b) -> MaybeTable a -> Expr (Maybe db)
177201f $? ma@(MaybeTable _ a) = case nullabilization @b of