Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I pass a typeclass dictionary to a function explicitly?

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?

like image 445
Alexis King Avatar asked Jun 30 '16 18:06

Alexis King


1 Answers

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?

like image 61
ErikR Avatar answered Oct 20 '22 14:10

ErikR