Difference between revisions of "DDC/PolymorphicUpdate"

From HaskellWiki
< DDC
Jump to navigation Jump to search
Line 59: Line 59:
 
, Base.Mutable %r0
 
, Base.Mutable %r0
 
</haskell>
 
</haskell>
  +
  +
In this type, we see the new closure term <hask>(box : %r0 $> a)</hask>. This term says that the closure contains an object named <hask>box</hask> which is in a region <hask>%r0</hask>, and the type of the object includes a variable <hask>a</hask>. When <hask>%r0</hask> is <hask>Mutable</hask> we say that <hask>a</hask> is ''dangerous'', and dangerous variables are never generalised when they are free in the (outer most) closure of a function.

Revision as of 07:02, 19 March 2008

Get/Set

Consider the following function:

makeGetSet :: forall a. a -> (() -> a, a -> ())
makeGetSet x
 = do 	box	= Just x
	get ()	= case box of { Just z -> z; }
	set z	= box#x #= z
	(get, set)

This function allocates a box which can store a value, and returns a tuple of functions to get and set that value.

As the function is polymorphic, we can create boxes of whatever type we would like:

main ()
 = do	getSet :: (() -> Int, Int -> ())
        getSet	= makeGetSet 5

 	out $ fst getSet ()   -- prints '5'

	snd getSet 23         -- update the box
	out $ fst getSet ()   -- prints '23'

The trouble comes when we create a box containing a value of polymorphic type. Without closure typing we could define:

        ...
        getSet2 :: forall a. (() -> [a], [a] -> ())
        getSet2 = makeGetSet []

When a list is empty, we can treat it as being of any type (forall a. [a]), but suppose we update the box containing it at two different types...

       snd getSet2 [23]
       snd getSet2 ["trouble"]

       out $ fst getSet2 ()

The type of getSet2 has forall a. at the front, so there is nothing to stop us from calling the set function at both [Int] and [String], but what should the type be when use the get function in the last line?

Dangerous type variables

Ultimately, the problem illustrated above arose because there wasn't a mechanism to track the sharing of data between successive calls to getSet2. When makeGetSet was evaluated it created a shared object (the box) and then returned functions that had this object free in their closure.

In Disciple, makeGetSet has the full type:

makeGetSet
        :: forall a %r0 %r1
        .  a -> Tuple2 %r1 (() -(!e0 $c0)> a) (a -(!e1 $c1)> ())
        :- !e0        = !Read %r0
        ,  !e1        = !{!Read %r0; !Write %r0}
        ,  $c0        = ${box : %r0; box : %r0 $> a}
        ,  $c1        = ${box : %r0; box : %r0 $> a}
        ,  Base.Mutable %r0

In this type, we see the new closure term (box : %r0 $> a). This term says that the closure contains an object named box which is in a region %r0, and the type of the object includes a variable a. When %r0 is Mutable we say that a is dangerous, and dangerous variables are never generalised when they are free in the (outer most) closure of a function.