Given a variable of type Dynamic
, it it possible to take advantage of the type classes of the internal variable without conditioning on the exact type? For example, let's say I want to write a function prettyShow
. If the internal type is an instance of Show
, then we should use that instance; otherwise, we should use the instance of the Dynamic
class. In code, this might look like:
prettyShow :: Dynamic -> String
prettyShow x = case fromDynamic x :: (forall a. Show a => Maybe a) of
Nothing -> show x
Just y -> show y
Edit: Since it appears this can't be done directly, what are some good workaround that can be done?
This can be done using the implementation of Dynamic
in the open-typerep library (if you accept using generic programming and lots of GHC extensions).
{-# LANGUAGE TypeOperators #-}
import Data.TypeRep
type Types = BoolType :+: IntType :+: ListType
x, y :: Dynamic Types
x = toDyn [False,True]
y = toDyn [1, 2 :: Int]
test1 = show x
test2 = show y
The definition of show
is simple, and you can use the library to define other functions over dynamic values.
In the above example I used a closed type universe Type
. But using Data Types à la Carte tricks you can also define functions for open universes. For example, show
itself is open.
Performance
A simple benchmark shows that this Dynamic
is 2-3 times slower than Data.Dynamic
in base
for the small type universe used above. Increasing the universe to 30 type constructors makes it a bit more than 10 times slower.
Auto deriving for new types
open-typerep
supports making universes from a small number of predefined representation types. It should in principle be possible to use TemplateHaskell to auto-derive representations for new types, but it will be tricky to generate the right instances for Witness
and PWitness
as these depend on what other instances are available. (Witness
is used e.g. by the Show
instance for Dynamic
.)
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