{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE TypeInType #-} -- TODO -- Updater -- easier -- this one's probably not needed -- NullMaker -- easier -- Constant -- harder -- QueryRunner -- harder module Opaleye.Internal.TypeFamilies where import Opaleye.Column (Column, Nullable) import qualified Opaleye.Field as F type family IMap f a data HT data OT data NullsT data WT -- | Used in 'RecordField' and 'TableRecordField' for a non-nullable -- field type NN = 'F.NonNullable -- | Used in 'RecordField' and 'TableRecordField' for a nullable field type N = 'F.Nullable data Optionality = OReq | OOpt -- | 'TableRecordField' for a required field type Req = 'OReq -- | 'TableRecordField' for an optional field type Opt = 'OOpt type family A (a :: Arr h k1 k2) (b :: k1) :: k2 data Arr h k1 k2 where K :: k1 -> Arr h k2 k1 S :: Arr h k1 (k2 -> k3) -> Arr h k1 k2 -> Arr h k1 k3 I :: Arr h k1 k1 H :: h -> Arr h k2 k3 type (:<*>) = 'S type Pure = 'K type (:<$>) f = (:<*>) (Pure f) type Id = 'I type (:<|) f x = A f x type instance A 'I a = a type instance A ('K k1) _ = k1 type instance A ('S f x) a = (A f a) (A x a) data C a = C (a, a, F.Nullability) data TC a = TC ((a, a, F.Nullability), Optionality) type instance A ('H HT) ('C '(h, o, NN)) = h type instance A ('H HT) ('C '(h, o, N)) = Maybe h type instance A ('H OT) ('C '(h, o, NN)) = Column o type instance A ('H OT) ('C '(h, o, N)) = Column (Nullable o) type instance A ('H NullsT) ('C '(h, o, n)) = Column (Nullable o) type instance A ('H HT) ('TC '(t, b)) = A ('H HT) ('C t) type instance A ('H OT) ('TC '(t, b)) = A ('H OT) ('C t) type instance A ('H WT) ('TC '(t, Req)) = A ('H OT) ('C t) type instance A ('H WT) ('TC '(t, Opt)) = Maybe (A ('H OT) ('C t)) type instance A ('H NullsT) ('TC '(t, b)) = A ('H NullsT) ('C t) type RecordField f a b c = A f ('C '(a, b, c)) type TableRecordField f a b c d = A f ('TC '( '(a, b, c), d)) {-# DEPRECATED TableField "Use 'TableRecordField' instead. Will be remoed in version 0.8." #-} type TableField f a b c d = TableRecordField f a b c d -- | Type families parameter for Haskell types ('String', 'Int', etc.) type H = 'H HT -- | Type families parameter for Opaleye types ('Opaleye.Field.Field' -- 'Opaleye.SqlString', 'Opaleye.Field.Field' 'Opaleye.SqlInt4', etc.) type O = 'H OT -- | Type families parameter for nulled Opaleye types -- ('Opaleye.Field.FieldNullable' 'Opaleye.SqlString', -- 'Opaleye.Field.FieldNullable' 'Opaleye.SqlInt4', etc.) type Nulls = 'H NullsT -- | Type families parameter for Opaleye write types (i.e. wrapped in -- 'Maybe' for optional types) type W = 'H WT type F = 'H