My aim is to write function that takes some polymorphic values and list with typereps representing concrete types. It returns new list with the same values but already casted to concrete types specified via typereps.
Let we have such list of values: ["one", "two"]
with -XOverloadedStrings
enabled.
Respectively, type of each one is IsString a => a
.
List of typereps we could get in such way:
import Data.Typeable (Proxy(..), typeRep)
import Data.Text (Text)
[typeRep (Proxy :: Proxy String), typeRep (Proxy :: Proxy ByteString)]
Is there any way to get "one"
of type String
and "two"
of type ByteString
?
P.S. To prevent error according to list containing values of different types, we may wrap every value in Dynamic.
, as in the example below(pseudocode):
{-# LANGUAGE ParallelListComp #-}
import Data.Dynamic (toDyn)
[ toDyn (val :: type') | val <- vals | type' <- concreteTypes ]
It could be done using Template Haskell, but it will be too ugly.
I can't really imagine your purpose, but the code will probably look something like this. I'm using the new Type.Reflection
interface because I'm more familiar with it than with the classic Data.Typeable
, but that should work for this too.
import Type.Reflection
types :: [SomeTypeRep]
types = [SomeTypeRep (typeRep @String), SomeTypeRep (typeRep @Text)]
strings :: [String]
strings = ["one", "two"]
converted :: [Dynamic]
converted = fromJust $ zipWithM convert types strings
convert :: SomeTypeRep -> String -> Maybe Dynamic
convert (SomeTypeRep rep) s
| Just HRefl <- eqTypeRep rep (typeRep @String) = Just $ toDynamic s
| Just HRefl <- eqTypeRep rep (typeRep @Text) = Just $ toDynamic (fromString s)
| otherwise = Nothing