{-# LANGUAGE TypeApplications #-}

-- | Simple example of a generic function
module Data.Record.Generic.LowerBound (
    LowerBound(..)
  , glowerBound
  ) where

import Data.Record.Generic
import qualified Data.Record.Generic.Rep as Rep

{-------------------------------------------------------------------------------
  General definition
-------------------------------------------------------------------------------}

-- | Types with a lower bound
class LowerBound a where
  lowerBound :: a

instance LowerBound Word where lowerBound :: Word
lowerBound = Word
0
instance LowerBound Bool where lowerBound :: Bool
lowerBound = Bool
False
instance LowerBound Char where lowerBound :: Char
lowerBound = Char
'\x0000'
instance LowerBound ()   where lowerBound :: ()
lowerBound = ()
instance LowerBound [a]  where lowerBound :: [a]
lowerBound = []

{-------------------------------------------------------------------------------
  Generic definition
-------------------------------------------------------------------------------}

glowerBound :: (Generic a, Constraints a LowerBound) => a
glowerBound :: a
glowerBound = Rep I a -> a
forall a. Generic a => Rep I a -> a
to (Rep I a -> a) -> Rep I a -> a
forall a b. (a -> b) -> a -> b
$ Proxy LowerBound -> (forall x. LowerBound x => I x) -> Rep I a
forall a (c :: * -> Constraint) (f :: * -> *).
(Generic a, Constraints a c) =>
Proxy c -> (forall x. c x => f x) -> Rep f a
Rep.cpure (Proxy LowerBound
forall k (t :: k). Proxy t
Proxy @LowerBound) (x -> I x
forall a. a -> I a
I x
forall a. LowerBound a => a
lowerBound)