{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} -- | -- Module : Database.Record.Persistable -- Copyright : 2013 Kei Hibino -- License : BSD3 -- -- Maintainer : ex8k.hibino@gmail.com -- Stability : experimental -- Portability : unknown -- -- This module defines interfaces -- between Haskell type and list of SQL type. module Database.Record.Persistable ( -- * Specify SQL type PersistableSqlType, runPersistableNullValue, unsafePersistableSqlTypeFromNull, -- * Specify record width PersistableRecordWidth, runPersistableRecordWidth, unsafePersistableRecordWidth, unsafeValueWidth, (<&>), maybeWidth, -- * Inference rules for proof objects PersistableType(..), sqlNullValue, PersistableWidth (..), derivedWidth ) where -- | Proof object to specify type 'q' is SQL type newtype PersistableSqlType q = PersistableSqlType q -- | Null value of SQL type 'q'. runPersistableNullValue :: PersistableSqlType q -> q runPersistableNullValue (PersistableSqlType q) = q -- | Unsafely generate 'PersistableSqlType' proof object from specified SQL null value which type is 'q'. unsafePersistableSqlTypeFromNull :: q -- ^ SQL null value of SQL type 'q' -> PersistableSqlType q -- ^ Result proof object unsafePersistableSqlTypeFromNull = PersistableSqlType -- | Proof object to specify width of Haskell type 'a' -- when converting to SQL type list. newtype PersistableRecordWidth a = PersistableRecordWidth Int -- | Get width 'Int' value of record type 'a'. runPersistableRecordWidth :: PersistableRecordWidth a -> Int runPersistableRecordWidth (PersistableRecordWidth w) = w -- | Unsafely generate 'PersistableRecordWidth' proof object from specified width of Haskell type 'a'. unsafePersistableRecordWidth :: Int -- ^ Specify width of Haskell type 'a' -> PersistableRecordWidth a -- ^ Result proof object unsafePersistableRecordWidth = PersistableRecordWidth -- | Unsafely generate 'PersistableRecordWidth' proof object for Haskell type 'a' which is single column type. unsafeValueWidth :: PersistableRecordWidth a unsafeValueWidth = unsafePersistableRecordWidth 1 -- | Derivation rule of 'PersistableRecordWidth' for tuple (,) type. (<&>) :: PersistableRecordWidth a -> PersistableRecordWidth b -> PersistableRecordWidth (a, b) a <&> b = PersistableRecordWidth $ runPersistableRecordWidth a + runPersistableRecordWidth b -- | Derivation rule of 'PersistableRecordWidth' from from Haskell type 'a' into for Haskell type 'Maybe' 'a'. maybeWidth :: PersistableRecordWidth a -> PersistableRecordWidth (Maybe a) maybeWidth = PersistableRecordWidth . runPersistableRecordWidth -- | Axiom of 'PersistableRecordWidth' for Haskell unit () type. voidWidth :: PersistableRecordWidth () voidWidth = unsafePersistableRecordWidth 0 -- | Interface of inference rule for 'PersistableSqlType' proof object class Eq q => PersistableType q where persistableType :: PersistableSqlType q -- | Inferred Null value of SQL type. sqlNullValue :: PersistableType q => q sqlNullValue = runPersistableNullValue persistableType -- | Interface of inference rule for 'PersistableRecordWidth' proof object class PersistableWidth a where persistableWidth :: PersistableRecordWidth a -- | Inference rule of 'PersistableRecordWidth' proof object for tuple ('a', 'b') type. instance (PersistableWidth a, PersistableWidth b) => PersistableWidth (a, b) where persistableWidth = persistableWidth <&> persistableWidth -- | Inference rule of 'PersistableRecordWidth' proof object for 'Maybe' type. instance PersistableWidth a => PersistableWidth (Maybe a) where persistableWidth = maybeWidth persistableWidth -- | Inference rule of 'PersistableRecordWidth' for Haskell unit () type. Derive from axiom. instance PersistableWidth () where persistableWidth = voidWidth -- | Pass type parameter and inferred width value. derivedWidth :: PersistableWidth a => (PersistableRecordWidth a, Int) derivedWidth = (pw, runPersistableRecordWidth pw) where pw = persistableWidth