Skip to content

Instantly share code, notes, and snippets.

@Profpatsch
Created December 15, 2022 07:50
Show Gist options
  • Save Profpatsch/ff2a46bb4d99b2a2cfa3b109d7a6cf46 to your computer and use it in GitHub Desktop.
Save Profpatsch/ff2a46bb4d99b2a2cfa3b109d7a6cf46 to your computer and use it in GitHub Desktop.
Labelled values in Haskell that are accessible with record dot syntax
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-}
module Label
( Label,
label,
label',
)
where
import Data.Data (Proxy (..))
import Data.Typeable (Typeable)
import GHC.Records (HasField (..))
import GHC.TypeLits (Symbol)
-- | A labelled value.
--
-- Use 'label'/'label'' to construct,
-- then use dot-syntax to get the inner value.
newtype Label (label :: Symbol) value = Label value
deriving stock (Show, Eq, Ord)
deriving newtype (Typeable)
-- | Attach a label to a value; should be used with a type application to name the label.
--
-- @@
-- let f = label @"foo" 'f'@ :: Label "foo" Char
-- in f.foo :: Char
-- @@
--
-- Use dot-syntax to get the labelled value.
label :: forall label value. value -> Label label value
label value = Label value
-- | Attach a label to a value; Pass it a proxy with the label name in the argument type.
-- This is intended for passing through the label value;
-- you can also use 'label'.
--
--
-- @@
-- let f = label' (Proxy @"foo") 'f'@ :: Label "foo" Char
-- in f.foo :: Char
-- @@
--
-- Use dot-syntax to get the labelled value.
label' :: forall label value. (Proxy label) -> value -> Label label value
label' Proxy value = Label value
-- | Fetches the labelled value.
instance HasField label (Label label value) value where
getField :: (Label label value) -> value
getField (Label value) = value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment