Skip to content

Instantly share code, notes, and snippets.

@zlondrej
Created May 29, 2024 14:54
Show Gist options
  • Save zlondrej/2d8356af076207c4e885834005995f36 to your computer and use it in GitHub Desktop.
Save zlondrej/2d8356af076207c4e885834005995f36 to your computer and use it in GitHub Desktop.
I was experimenting on how to adjust constraints depending on type level list of modifiers.
{- stack script
--resolver lts-21.11
--package singleton-bool
--package text
-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module ParameterConstraints where
import Data.Kind (Constraint, Type)
import Data.Proxy (Proxy (..))
import Data.Text (Text)
-- Modifiers
data HasDefault
data AllowEmpty
data CanRead
data CanShow
data SomeMod
-- Experiment
class DefaultParameter a where
defaultParameterValue :: a
class EmptyParameter a where
emptyParameterValue :: a
type family ParamConstraints (mods :: [Type]) (a :: Type) :: Constraint where
ParamConstraints '[] a = ()
ParamConstraints (HasDefault ': mods) a = (DefaultParameter a, ParamConstraints mods a)
ParamConstraints (AllowEmpty ': mods) a = (EmptyParameter a, ParamConstraints mods a)
ParamConstraints (CanRead ': mods) a = (Read a, ParamConstraints mods a)
ParamConstraints (CanShow ': mods) a = (Show a, ParamConstraints mods a)
ParamConstraints (_ ': mods) a = ParamConstraints mods a
getModParam :: forall mods m a. (Monad m, ParamConstraints mods a) => Proxy mods -> m a
getModParam _ = undefined
-- > stack ghci --package singleton-bool --package text --ghci-options -XTypeApplications --ghci-options -XDataKinds ParameterConstraints.hs
--
-- :set -XTypeApplications
-- :set -XDataKinds
--
-- >>> :t getModParam (Proxy @'[])
-- = getModParam (Proxy @'[]) :: Monad m => m a
--
-- >>> :t getModParam (Proxy @'[CanRead, CanShow])
-- = getModParam (Proxy @'[CanRead, CanShow])
-- :: (Monad m, Read a, Show a) => m a
--
-- >>> :t getModParam (Proxy @'[SomeMod, AllowEmpty])
-- = getModParam (Proxy @'[SomeMod, AllowEmpty])
-- :: (Monad m, EmptyParameter a) => m a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment