Haskell has a type called
Dynamic which resembles a dynamically-typed variable in some other languages.
Dynamic is a sort of wrapper that can hold a value of any type.
We might use this, for example, to construct a heterogeneous list – that is, a list containing elements of different types.
toDyn creates a
Dynamic. Here we apply it to arguments of three different types – a
Integer, and a
String – to construct a list of three
import Data.Dynamic import Data.Foldable = mixedList True [ toDyn 5 :: Integer) , toDyn ("hey" , toDyn ]
This example program iterates over the list and prints a message describing each element. (We will define the
message function later below.)
= main $ \d -> for_ mixedList putStrLn (message d)
The only thing we can do with a
Dynamic is use the
fromDynamic function to attempt to cast it back to its original type. If the cast succeeds, it returns
Just the original value; otherwise it returns
We have written the
recognizeType function to generate two kinds of messages: one if the dynamic type is
Integer, and another if the type is
asum function chooses the first
Just among the list of
= recognizeType d asum d :: Maybe Integer) >>= \x -> [ (fromDynamicJust (show x ++ " is an integer") d :: Maybe Bool) >>= \x -> , (fromDynamicJust ("The answer is " ++ (if x then "yes" else "no")) ]
It is possible that neither of the possibilities above succeeded. A
Dynamic can hold a value of any type, and since there is an unlimited number of types in the world, we cannot check them all. So we have a last resort: if all else fails and the
Nothing, we return an apologetic message that contains the name of the type.
= message d case (recognizeType d) of Just x -> x Nothing -> "Unrecognized type: " ++ show (dynTypeRep d)
Since we neglected to write a case to handle the
String type, the third message says “unrecognized type”.
$ runhaskell dynamic.hs The answer is yes 5 is an integerUnrecognized type: [Char]