uom-plugin-0.1.0.0: src/Data/UnitsOfMeasure/Singleton.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
-- | This module defines singleton types for integers and concrete
-- units.
module Data.UnitsOfMeasure.Singleton
( -- * Singletons for units
SUnit(..)
, forgetSUnit
, KnownUnit(..)
, unitVal
-- * Singletons for lists
, SList(..)
, KnownList(..)
) where
import GHC.TypeLits
import Data.UnitsOfMeasure.Internal
-- | Singleton type for concrete units of measure represented as lists
-- of base units
data SUnit (u :: UnitSyntax Symbol) where
SUnit :: SList xs -> SList ys -> SUnit (xs :/ ys)
-- | Singleton type for lists of base units
data SList (xs :: [Symbol]) where
SNil :: SList '[]
SCons :: KnownSymbol x => proxy x -> SList xs -> SList (x ': xs)
-- | Extract the runtime syntactic representation from a singleton unit
forgetSUnit :: SUnit u -> UnitSyntax String
forgetSUnit (SUnit xs ys) = forgetSList xs :/ forgetSList ys
forgetSList :: SList xs -> [String]
forgetSList SNil = []
forgetSList (SCons px xs) = symbolVal px : forgetSList xs
-- | A constraint @'KnownUnit' u@ means that @u@ must be a concrete
-- unit that is statically known but passed at runtime
class KnownUnit (u :: UnitSyntax Symbol) where
unitSing :: SUnit u
instance (KnownList xs, KnownList ys) => KnownUnit (xs :/ ys) where
unitSing = SUnit listSing listSing
-- | A constraint @'KnownList' xs@ means that @xs@ must be a list of
-- base units that is statically known but passed at runtime
class KnownList (xs :: [Symbol]) where
listSing :: SList xs
instance KnownList '[] where
listSing = SNil
instance (KnownSymbol x, KnownList xs) => KnownList (x ': xs) where
listSing = SCons (undefined :: proxy x) listSing
-- | Extract the runtime syntactic representation of a 'KnownUnit'
unitVal :: forall proxy u . KnownUnit u => proxy u -> UnitSyntax String
unitVal _ = forgetSUnit (unitSing :: SUnit u)