Sorry, I couldn't imagine any better title for the question, so please read ahead. Imagine that we have a closed type family that maps every type to it's corresponding Maybe
except maybes themselves:
type family Family x where
Family (Maybe x) = Maybe x
Family x = Maybe x
We can even declare a function using that type family:
doMagic :: a -> Family a
doMagic = undefined
exampleA = doMagic $ Just ()
exampleB = doMagic $ ()
Playing with it in GHCi shows that it is ok to evaluate the type of this function application:
*Strange> :t exampleA
exampleA :: Maybe ()
*Strange> :t exampleB
exampleB :: Maybe ()
The question is if it is possible to provide any implementation of the doMagic
function except undefined
? Let's for example say that I would like to wrap every value into a Just
constructor, except Maybes which should remain intact, how could I do that? I tried using typeclasses, but failed to write a compileable signature for doMagic function if not using closed type families, could somebody please help me?
You can use another closed type family to distinguish Maybe x
from x
and then you can use another typeclass to provide separate implementations of doMagic
for these two cases. Quick and dirty version:
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses,
FlexibleInstances, UndecidableInstances, ScopedTypeVariables #-}
type family Family x where
Family (Maybe x) = Maybe x
Family x = Maybe x
data True
data False
type family IsMaybe x where
IsMaybe (Maybe x) = True
IsMaybe x = False
class DoMagic a where
doMagic :: a -> Family a
instance (DoMagic' (IsMaybe a) a (Family a)) => DoMagic a where
doMagic = doMagic' (undefined :: IsMaybe a)
class DoMagic' i a r where
doMagic' :: i -> a -> r
instance DoMagic' True (Maybe a) (Maybe a) where
doMagic' _ = id
instance DoMagic' False a (Maybe a) where
doMagic' _ = Just
exampleA = doMagic $ Just ()
exampleB = doMagic $ ()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With