1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
<sect> <idx/Dynamic/
<label id="sec:Dynamic">
<p>
The <tt/Dynamic/ library provides cheap-and-cheerful dynamic types for
Haskell. A dynamically typed value is one which carries type
information with it at run-time, and is represented here by the
abstract type <tt/Dynamic/. Values can be converted into <tt/Dynamic/
ones, which can then be combined and manipulated by the program using
the operations provided over the abstract, dynamic type. One of
these operations allows you to (try to) convert a dynamically-typed
value back into a value with the same (monomorphic) type it had before
converting it into a dynamically-typed value. If the dynamically-typed
value isn't of the desired type, the coercion will fail.
The <tt/Dynamic/ library is capable of dealing with monomorphic types
only; no support for polymorphic dynamic values, but hopefully that
will be added at a later stage.
Examples where this library may come in handy (dynamic types, really -
hopefully the library provided here will suffice) are: persistent
programming, interpreters, distributed programming etc.
The following operations are provided over the <tt/Dynamic/ type:
<tscreen> <verb>
data Dynamic -- abstract, instance of: Show --
toDyn :: Typeable a => a -> Dynamic
fromDyn :: Typeable a => Dynamic -> a -> a
fromDynamic :: Typeable a => Dynamic -> Maybe a
</verb></tscreen>
<itemize>
<item> <tt/toDyn/ converts a value into a dynamic one, provided
<tt/toDyn/ knows the (concrete) type representation of the value.
The <tt/Typeable/ type class is used to encode this, overloading a
function that returns the type representation of a value. More on this
below.
<item> There's two ways of going from a dynamic value to one with
a concrete type: <tt/fromDyn/, tries to convert the dynamic value into
a value with the same type as its second argument. If this fails, the
default second argument is just returned. <tt/fromDynamic/ returns a
<tt/Maybe/ type instead, <tt/Nothing/ coming back if the conversion
was not possible.
<item>
The <tt/Dynamic/ type has got a <tt/Show/ instance which returns
a pretty printed string of the type of the dynamic value. (Useful when
debugging).
</itemize>
<sect1> <idx/Representing types/
<label id="sec:Dynamic:TypeRep">
<p>
Haskell types are represented as terms using the <tt/TypeRep/
abstract type:
<tscreen> <verb>
data TypeRep -- abstract, instance of: Eq, Show
data TyCon -- abstract, instance of: Eq, Show
mkTyCon :: String -> TyCon
mkAppTy :: TyCon -> [TypeRep] -> TypeRep
mkFunTy :: TypeRep -> TypeRep -> TypeRep
applyTy :: TypeRep -> TypeRep -> Maybe TypeRep
</verb></tscreen>
<itemize>
<item> <tt/mkAppTy/ applies a type constructor to a sequence of types,
returning a type.
<item> <tt/mkFunTy/ is a special case of <tt/mkAppTy/, applying
the function type constructor to a pair of types.
<item> <tt/applyTy/ applies a type to a function type. If possible,
the result type is returned.
<item> Type constructors are represented by the abstract type,
<tt/TyCon/.
<item>
Most importantly, <tt/TypeRep/s can be compared for equality.
Type equality is used when converting a <tt/Dynamic/ value into a
value of some specific type, comparing the type representation that
the <tt/Dynamic/ value embeds with equality of the type representation
of the type we're trying to convert the dynamically-typed value into.
<item>
To allow comparisons between <tt/TypeRep/s to be implemented
efficiently, the <em/abstract/ <tt/TyCon/ type is used, with
the constructor function <tt/mkTyCon/ provided:
<tscreen> <verb>
mkTyCon :: String -> TyCon
</verb></tscreen>
An implementation of the <tt/Dynamic/ interface guarantees the
following,
<tscreen> <verb>
mkTyCon "a" == mkTyCon "a"
</verb></tscreen>
A really efficient implementation is possible if we guarantee/demand
that the strings are unique, and for a particular type constructor,
the application <tt/mkTyCon/ to the string that represents the type
constructor is never duplicated. <bf/Q:/ <em>Would this constraint be
unworkable in practice?</em>
<item>
Both <tt/TyCon/ and <tt/TypeRep/ are instances of the <tt/Show/ type
classes. To have tuple types be shown in infix form, the <tt/Show/
instance guarantees that type constructors consisting of <tt/n/-commas,
i.e., (<tt/mkTyCon ",,,,"/), is shown as an <tt/(n+1)/ tuple in infix
form.
</itemize>
<sect1><idx>The Typeable class</idx>
<nidx>Typeable class</nidx>
<label id="sec:Dynamic:Typeable">
<p>
To ease the construction of <tt/Dynamic/ values, we
introduce the following type class to help working with <tt/TypeRep/s:
<tscreen><verb>
class Typeable a where
typeOf :: a -> TypeRep
</verb></tscreen>
<itemize>
<item> The <tt/typeOf/ function is overloaded to return the type
representation associated with a type.
<item> <bf/Important:/ The argument to <tt/typeOf/ is only used to
carry type information around so that overloading can be resolved.
<tt/Typeable/ instances should never, ever look at this argument.
<item> The <tt/Dynamic/ library provide <tt/Typeable/ instances
for all Prelude and Hugs/GHC extension library types. They are:
<tscreen><verb>
Prelude types:
Int, Char, Bool, Float, Double, Integer, (IO a),
[a], (Either a b), (Maybe a), (a->b),
(), (,), (,,), (,,,), (,,,,),
Ordering, Complex, Array, Handle
Hugs/GHC types:
Addr, Word8, Word16, Word32, Word64,
Int8,Int16,Int32,Int64,
ForeignObj, MVar, (ST s a), (StablePtr a)
GHC types:
Word, ByteArray, MutableByteArray
</verb></tscreen>
</itemize>
<sect1> <idx/Utility functions/
<label id="sec:Dynamic:util">
<p>
Operations for applying a dynamic function type to a
dynamically typed argument are commonly useful, and
also provided:
<tscreen> <verb>
dynApply :: Dynamic -> Dynamic -> Dynamic -- unsafe.
dynApplyMb :: Dynamic -> Dynamic -> Maybe Dynamic
</verb></tscreen>
|