-
Notifications
You must be signed in to change notification settings - Fork 5
References Tutorial
A reference is a property accessor. You can think of it as a setter and getter method. For example if you have a point datatype: data Point = Point Double Double
then, you may define references x
and y
to access the two Double
values inside the point. You can use the reference to get their values and also to modify them.
The simplest problem references solve is the problem of handling a large nested data structure. For example, take the following datatypes:
data Arrow = Arrow { from :: Point, to :: Point }
data Point = Point { x :: Double, y :: Double }
If you want to shift the arrow, you have to define a function that takes it to parts and repacks it:
shiftArrowX :: Double -> Arrow -> Arrow
shiftArrowX d (Arrow (Point fromX fromY) (Point toX toY))
= Arrow (Point (fromX + d) fromY) (Point (toX + d) toY)
This packing and repacking gets more complicated each time the representation grows. The references library solves this problem by letting you define references:
data Arrow = Arrow { _from :: Point, _to :: Point }
data Point = Point { _x :: Double, _y :: Double }
makeReferences ''Arrow
makeReferences ''Point
Then shiftArrowX
can be defined using references:
shiftArrowX :: Double -> Arrow -> Arrow
shiftArrowX d = (from &+& to) & y .- (+d)
The type of :t from
is (Monad w, Monad r) => Reference w r MU MU Arrow Arrow Point Point
The first 4 type variables are the write-read semantic monads of the reference. The last 4 are the type of the context type, and the accessed element.
We don't have any constraints (aside from Monad
) for w
and r
, and that shows that the from
element is always present in an arrow. Here the context type and the accessed element is present twice in the type. In other cases when the data type is polymorphic, using a reference may actually change the type of the context. For example, the type of the context and elements types for the reference just
(that accesses the possible existing element inside a Maybe
value) will be: (Maybe a) (Maybe b) a b
. That shows that by replacing the element inside a just with something of type b
, you will get a (Maybe b)
as a result