Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining Data.Dynamic and type classes

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?

like image 707
Mike Izbicki Avatar asked Apr 05 '14 03:04

Mike Izbicki


1 Answers

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.)

like image 97
emilaxelsson Avatar answered Oct 20 '22 05:10

emilaxelsson