persistable-record-0.4.0.0: src/Database/Record/Persistable.hs
{-# 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