Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: Show all the elements that are "showable" on a Hlist

I have tried

map show . mapMaybe fromDynamic $ [toDyn "one", toDyn (\x -> x::Integer), toDyn 3, toDyn ()]

but it returned

["()"]
like image 559
rbarreiro Avatar asked Feb 04 '13 21:02

rbarreiro


2 Answers

The problem is that fromDynamic must go to a monomorphic type. It is picking (), but with a type signature you could make it pick any other type.

To show it, you would need some function that tries all the possible types in turn. Probably you do not want to store the data like this, but want to store it bundled up with some operations (such as show).

There are two ways you could bundle. My favourite is to have all the functions pre-applied to the value (so for show, you just get a list of thunks of type String).

The other way is to also put the functions into a Dynamic (make sure they are the correct monomorphic type!) and then use dynApply.

like image 93
singpolyma Avatar answered Sep 22 '22 15:09

singpolyma


Your code does not do what you expect it to do. Long before the dynamic behaviour of Data.Dynamic kicks in, the Haskell type checker resolves the types. The type of the right part of the expression is

mapMaybe fromDynamic $ [toDyn "one", toDyn (\x -> x::Integer), toDyn 3, toDyn ()] :: Typeable b => [b]

and the type of the left part is

map show :: Show a => [a] -> [String]

so to combine these, the type variable b resp. a gets unified. If you were to compile this from a regular Haskell file, the compiler would give you a warning (The type variable `a' is ambigous). But in GHCi, the interpreter just defaults to ().

But this fixes the type of fromDynamic in the expression to Dynamic -> Maybe (), effectively selecting all elements of type ().

If you force the compiler to use a different type there, e.g. by specifying a type signature, you see that fromDynamic selects a different type:

Prelude Data.Dynamic Data.Maybe> map (show :: Integer -> String) . mapMaybe fromDynamic $ [toDyn "one", toDyn (\x -> x::Integer), toDyn 3, toDyn ()]
["3"]

Unfortunately, there is no way to achieve what you want: Select all elements whose type support a show instance, as that information is not available to fromDynamic.

like image 35
Joachim Breitner Avatar answered Sep 24 '22 15:09

Joachim Breitner