Created
May 29, 2024 14:54
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{- 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