| Version 1 (modified by benl, 3 years ago) |
|---|
Destructive Update
Update of base values
Values can be updated with the (:=) operator, which copies its second argument over its first.
main ()
= do x = 2
putStrLn $ show x -- prints '2'
x := 3
putStrLn $ show x -- prints '3'
Update of algebraic data
The structure of algebraic data can be modified with the (#=) operator. This replaces the constructor at a particular node with a new one.
We'll use a simple point type as an example. In this definition, x and y are field names and are local to the Point type. This is different from Haskell, where all field names become functions in the top level scope.
data Point
= Point { x :: Float; y :: Float; }
We'll also define an instance of the <hask>Show</hask> type-class, so we can print out the result.
instance Show Point where
show (Point x y) = parens (show x % "," % show y)
}}}
Values of `Point` type are constructed in the standard way, and we can use the field names to access their components.
{{{
main ()
= do point = Point 2.0 3.0 -- construct a new point
putStrLn $ show point -- prints '(2.0, 3.0)'
putStrLn $ show point.x -- prints '2.0'
}}}
Projecting the `x` field gives us the `Float` object inside `point`.
{{{
oldX = point.x
putStrLn $ show oldX -- prints '2.0'
}}}
Binding a literal value allocates a new object.
{{{
newX = 5.0
}}}
We can now make `point` reference this new object.
{{{
point#x #= newX
putStrLn $ show point -- prints '(5.0, 3.0)'
putStrLn $ show oldX -- oldX is still '2.0'
}}}
== Reference projections ==
In Disciple, we don't need to change our data definitions to include `Ref` or `IORef` types before we can update them. References are created on the fly with the reference projection operator `(#)`.
In the previous example, when we used `(#)` a reference was created which held a pointer ''into'' the `point` object.
{{{
(point # x) :: Ref Float
}}}
The `(#=)` operator is just a regular function which has type:
{{{
(#=) :: forall a. Ref a -> a -> ()
}}}
When we then evaluated:
{{{
point#x #= newX
}}}
The pointer inside `point` which used to reference `oldX` was updated to reference to `newX`.
