large-anon-0.1.0.0: test/Test/Infra/MarkStrictness.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
-- | Proof of concept: mark strictness at the type-level
--
-- This is an illustration of how to take advantage of the polykinded nature of
-- the advanced 'Record' interface.
module Test.Infra.MarkStrictness (
-- * Definition
MarkStrictness(..)
, Boxed(..)
) where
import Data.Kind
import Data.SOP.BasicFunctors
import Data.Record.Anon
import Test.Infra.DynRecord
import Test.Infra.DynRecord.Advanced
{-------------------------------------------------------------------------------
Definition
-------------------------------------------------------------------------------}
data MarkStrictness a = Strict a | Lazy a
data Boxed :: MarkStrictness Type -> Type where
BoxStrict :: !a -> Boxed (Strict a)
BoxLazy :: a -> Boxed (Lazy a)
{-------------------------------------------------------------------------------
Standard instances
-------------------------------------------------------------------------------}
instance Show a => Show (Boxed (Strict a)) where
show (BoxStrict x) = show x
instance Show a => Show (Boxed (Lazy a)) where
show (BoxLazy x) = show x
instance Eq a => Eq (Boxed (Strict a)) where
BoxStrict x == BoxStrict y = x == y
instance Eq a => Eq (Boxed (Lazy a)) where
BoxLazy x == BoxLazy y = x == y
{-------------------------------------------------------------------------------
Interop with 'DynRecord'
-------------------------------------------------------------------------------}
instance ToValue I a => ToValue Boxed (Lazy a) where
toValue (BoxLazy x) = toValue (I x)
instance ToValue I a => ToValue Boxed (Strict a) where
toValue (BoxStrict x) = toValue (I x)
-- | Type inference for a value
--
-- Just for the example, we infer all 'Int' fields are strict and all other
-- fields as lazy.
instance IsValue Boxed where
isValue (VI x) = Some $ ValidField $ BoxStrict x
isValue (VB x) = Some $ ValidField $ BoxLazy x
isValue (VC x) = Some $ ValidField $ BoxLazy x