Created
May 12, 2018 23:41
-
-
Save ch3pjw/0ab767bc9e6b4ac56e2b36b784d09598 to your computer and use it in GitHub Desktop.
Mashing together type-class constraints inside a parameterised existential datatype
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
{-# LANGUAGE | |
ConstraintKinds | |
, ExistentialQuantification | |
, FlexibleInstances | |
, MultiParamTypeClasses | |
, TypeOperators | |
, UndecidableSuperClasses | |
#-} | |
module Test where | |
import Data.Proxy | |
-- Not needed, just FYI this is where you get the Constraint kind from: | |
import GHC.Exts (Constraint) | |
-- NB, ctx :: Constraint | |
data Thing ctx = forall a. ctx a => Thing a | |
-- | This is simply to show that parameterising Thing works. Without | |
-- passing the `Show` class, this function wouldn't compile. | |
doShow :: Thing Show -> String | |
doShow (Thing a) = show a | |
-- This is some slightly mind-bending magic that I got from | |
-- https://github.com/glaebhoerl/exists/blob/master/Control/Constraint/Combine.hs | |
-- I think it works simply because when you specify a constraint like | |
-- (Num :&: Show) a => ... | |
-- That just pulls in both the superclass constraints on the LHS of the below. | |
-- NB, it needs the expected MultiParamTeypClasses and FlexibleInstances extensions, | |
-- and _also_ the UndecidableSuperClasses one - scary! | |
class (c a, d a) => (c :&: d) a | |
instance (c a, d a) => (c :&: d) a | |
infixl 7 :&: | |
-- But now we can write this sexy beast: | |
doNumShow :: Thing (Num :&: Show) -> String | |
doNumShow (Thing num) = show num | |
-- Which will run like | |
-- > doNumShow 3 | |
-- "3" | |
-- > doNumShow "hello" | |
-- No instance Num a... | |
-- NB we couldn't use a simple constraint synonym like | |
-- type Mash c1 c2 a = (c1 a, c2 a) | |
-- because type aliases cannot be partially applied! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment