[Haskell-cafe] Restrict values in type

oleg at okmij.org oleg at okmij.org
Fri Jan 17 03:30:30 UTC 2014


> The only bit I don't quite understand is why the following code implies an
> "or" relation in the type constraint of repr.

> > data Stroke =
> >    Line Point Point (forall repr. (CirclePen repr, RectPen repr) => repr)
> >  | Arc Point Point (forall repr. (CirclePen repr) => repr)
> >  | Spot Point (forall repr.
> >                (CirclePen repr, RectPen repr, ArbitraryPen repr) => repr)

> To me this reads that repr should be both a CirclePen and a RectPen in
> order to satisfy the type constraint in the case of Line, but it seems that
> it is accepting a CirclePen or a RectPen (which is the desired behaviour,
> so I'm not complaining).

This point is indeed confusing. Perhaps yet another explanation might
be helpful. Added to the already given, it might help reaching the
critical mass.

First, it seems that the dictionary passing implementation of type
classes makes things clearer. This implementation realizes,
informally, double arrow as a simple arrow. For example, the declaration

> class CirclePen repr where
>     circle :: Float -> repr

is translated to a dictionary declaration

> data CirclePenDict repr = CirclePenDict{circle :: Float -> repr}

and a bounded polymorphic function or value like

> CirclePen repr => repr
is realized as
> CirclePenDict repr -> repr
Double arrow turns simple arrow.

Therefore,

> data Stroke =
>     Line Point Point (forall repr. (CirclePen repr, RectPen repr) => repr)

becomes

> data Stroke =
>     Line Point Point (forall repr. 
>         (CirclePenDict repr, RectPenDict repr) -> repr)

We can make two different lines, with the circle pen shape:
> -- Line p1 p2 (circle 10)
> stroke1 = Line' p0 p1 (\(circledict, rectdict) -> circle circledict 10)

or with the rectangular pen shape.
> -- Line p1 p2 (circle 10 20)
> stroke2 = Line' p0 p1 (\(circledict, rectdict) -> rectangle rectdict 10 20)

Obviously we cannot make Lines with the Arbitrary pen shape since we
will receive from the user only circledict and rectdict but no
arbitrarypendict.

Suppose we are communicating over a network. If I can send you
_either_ a boolean or an integer, you have to be prepared to handle
_both_. From a different point of view: if you send me the handler for
a boolean _and_ the handler for an integer, it becomes my choice which
one to invoke. (Incidentally, what I just described is a subset of
session types for pi-calculus.)

At this point de Morgan laws may spring to mind. Here is a related
explanation of using open records to implement open unions.

        http://okmij.org/ftp/Haskell/generics.html#PolyVariant










More information about the Haskell-Cafe mailing list