on ae4a786 help sign in
rel8/src/Rel8/Schema/Null.hs
110 lines 2.8 kB history raw
1{-# language ConstraintKinds #-}
2{-# language DataKinds #-}
3{-# language FlexibleContexts #-}
4{-# language FlexibleInstances #-}
5{-# language GADTs #-}
6{-# language MultiParamTypeClasses #-}
7{-# language RankNTypes #-}
8{-# language StandaloneKindSignatures #-}
9{-# language TypeFamilies #-}
10{-# language UndecidableInstances #-}
11{-# language UndecidableSuperClasses #-}
13module Rel8.Schema.Null
14 ( Nullify, Unnullify
15 , NotNull
16 , Homonullable
17 , Nullity( Null, NotNull )
18 , Nullable, nullable
19 , Sql
20 )
21where
23-- base
24import Data.Kind ( Constraint, Type )
25import Prelude
28type IsMaybe :: Type -> Bool
29type family IsMaybe a where
30 IsMaybe (Maybe _) = 'True
31 IsMaybe _ = 'False
34type Unnullify' :: Bool -> Type -> Type
35type family Unnullify' isMaybe ma where
36 Unnullify' 'False a = a
37 Unnullify' 'True (Maybe a) = a
40type Unnullify :: Type -> Type
41type Unnullify a = Unnullify' (IsMaybe a) a
44type Nullify' :: Bool -> Type -> Type
45type family Nullify' isMaybe a where
46 Nullify' 'False a = a
47 Nullify' 'True a = Maybe a
50type Nullify :: Type -> Type
51type Nullify a = Maybe (Unnullify a)
54-- | @nullify a@ means @a@ cannot take @null@ as a value.
55type NotNull :: Type -> Constraint
56class (Nullable a, IsMaybe a ~ 'False) => NotNull a
57instance (Nullable a, IsMaybe a ~ 'False) => NotNull a
60-- | @Homonullable a b@ means that both @a@ and @b@ can be @null@, or neither
61-- @a@ or @b@ can be @null@.
62type Homonullable :: Type -> Type -> Constraint
63class IsMaybe a ~ IsMaybe b => Homonullable a b
64instance IsMaybe a ~ IsMaybe b => Homonullable a b
67type Nullity :: Type -> Type
68data Nullity a where
69 NotNull :: NotNull a => Nullity a
70 Null :: NotNull a => Nullity (Maybe a)
73type Nullable' :: Bool -> Type -> Constraint
74class
75 ( IsMaybe a ~ isMaybe
76 , IsMaybe (Unnullify a) ~ 'False
77 , Nullify' isMaybe (Unnullify a) ~ a
78 ) => Nullable' isMaybe a
79 where
80 nullable' :: Nullity a
83instance IsMaybe a ~ 'False => Nullable' 'False a where
84 nullable' = NotNull
87instance IsMaybe a ~ 'False => Nullable' 'True (Maybe a) where
88 nullable' = Null
91-- | @Nullable a@ means that @rel8@ is able to check if the type @a@ is a
92-- type that can take @null@ values or not.
93type Nullable :: Type -> Constraint
94class Nullable' (IsMaybe a) a => Nullable a
95instance Nullable' (IsMaybe a) a => Nullable a
98nullable :: Nullable a => Nullity a
99nullable = nullable'
102-- | The @Sql@ type class describes both null and not null database values,
103-- constrained by a specific class.
104--
105-- For example, if you see @Sql DBEq a@, this means any database type that
106-- supports equality, and @a@ can either be exactly an @a@, or it could also be
107-- @Maybe a@.
108type Sql :: (Type -> Constraint) -> Type -> Constraint
109class (constraint (Unnullify a), Nullable a) => Sql constraint a
110instance (constraint (Unnullify a), Nullable a) => Sql constraint a