Let’s say I have some typeclass:
data Foo = Foo deriving (Show)
class Monad m => MonadFoo m where
getFoo :: m Foo
Since GHC implements typeclasses via dictionary passing (uses of SPECIALIZE
notwithstanding), it effectively transforms getFoo
into something like the following under the hood:
data MonadFooDict m = MonadFooDict { getFoo :: m Foo }
...and it inserts an additional argument at the beginning of calls to getFoo
that threads the dictionary around.
Sometimes, I might want to pick an instance dynamically, so passing a dictionary myself might be desirable. I can simulate this myself by creating an instance that will thread the dictionary around for me.
newtype DynamicMonadFoo a = DynamicMonadFoo
{ runFoo :: MonadFooDict DynamicMonadFoo -> a }
deriving ( Functor, Applicative, Monad
, MonadReader (MonadFooDict DynamicMonadFoo) )
instance MonadFoo DynamicMonadFoo where
getFoo = join $ asks _getFoo
Now, given some function with a MonadFoo
constraint, I can use the runFoo
function to pass it an explicit typeclass dictionary:
showCurrentFoo :: MonadFoo m => m String
showCurrentFoo = do
foo <- getFoo
return ("current foo: " ++ show foo)
ghci> runFoo showCurrentFoo MonadFooDict { _getFoo = return Foo }
"current foo: Foo"
This is really cool, but it seems like such a simple task that GHC might expose some sort of library to do this without all the boilerplate (and ideally in a way that would work more nicely with non-monadic typeclasses). Given that GHC has some “reflection-esque” capabilities like Data.Typeable
, this doesn’t seem outside the realm of possibility, but I’m not sure if it actually exists in some form.
Do any existing built-ins or other libraries allow doing this more automatically?
There is an article on this at the School of Haskell:
Reflecting values to types and back
See the section towards the end entitled Dynamically constructing type-class instances and But what about manual dictionaries?
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