[Haskell-cafe] Multi-param typeclass as superclass of Single-param typeclasses

Ben Doyle benjamin.peter.doyle at gmail.com
Thu Oct 26 17:09:48 UTC 2017


Welcome! You can certainly express the constraint you want. But you can't
do what you're trying to do with ShapeBox.

Let's take those two in reverse order. Before I start, though, an
obligatory warning (with the assumption that you're new to Haskell, as well
as this list): object orientation is usually not the best way to go in
Haskell. I don't mean to shame you for the question; it's a good learning
exercise. But in most practical cases plain old data and functions will
serve you better than a bunch of ad-hoc typeclasses.

So. We have an existential type, ShapeBox, that stores a Shape but hides
what Shape it is. And it seems that you'd like to be able write something
like:

    bar :: ShapeBox -> ShapeBox -> Bool
    bar (ShapeBox x) (ShapeBox y) = intersect x y

The trouble is that the instance of intersect we call depends on the actual
types of x and y, and we don't know those types (because we've hidden them
on purpose). If x and y are both Circles we need to use the Intersect
Circle Circle instance. If instead y is a Square we must use the Intersect
Circle Square instance, which in principle could do something entirely
different.

But there's hope. The way to declare the constraint you're after is to put
it on the instance declaration:

   instance (Shape a,  Shape b) => Intersect a b where
      intersect x y = ...

That says precisely that whenever a and b are shapes, you can intersect
them. The catch is that you must write this instance using only the
Shape-ness of x and y (which is all you know about them). So you won't be
able to have one way to intersect squares and circles, and another for
triangles and hexagons; you need to abstract all the knowledge that lets
you intersect into the Shape class.

The difference is between telling the compiler, "I promise I'll go and
write a suitable instance for each pair of Shapes, really" (which Haskell
won't allow), and saying "here's how to intersect any two shapes
whatsoever."

You may want to check out the diagrams package, which does something
similar with the class HasEnvelope.

Hope that helps,

Ben

On Thu, Oct 26, 2017 at 11:37 AM Tomasz Chronowski <
chronowski.tomasz at gmail.com> wrote:

> This is my first post here, so Hello everyone!
>
> In haskell it is possible to express a constraint "if 'a' and 'b' are
> instance of 'AB' then 'a' is instance of 'A' and 'b' is instance of 'B'":
>
> class (A a, B b) => AB a b ...
>
> Is it possible to express the converse - "if 'a' is instance of 'A' and
> 'b' is instance of 'B' then 'a' and 'b' are instance of 'AB'"?
>
> I want to create a list of shapes that can be tested for intersection. I
> think that possibility of expressing such constraints would allow to doing
> this in a "Object Oriented" way:
>
> data Circle = Circle { ... }
> data Square = Square { ... }
>
> class Shape a
>
> class Intersect a b where
>     intersect :: a -> b -> Bool
>
> -- pseudo haskell - "If 'a' is instance of 'Shape' and 'b' is instance of
> 'Shape' then 'a' and 'b' are instance of 'Intersect'"
> -- maybe some type hackery allows to express this?
> constraint Shape a, Shape b => Intersect a b
>
> instance Shape Circle
> instance Shape Square
>
> instance Intersect Circle Circle ...
> instance Intersect Circle Square ...
> ...
>
> data ShapeBox = forall a. Shape a => ShapeBox a
>
> foo = let x:y:_ = [ShapeBox Circle { ... }, ShapeBox Square { ... }, ...]
>       in intersect x y -- this should work because we know for sure that
> there is an instance of Intersect for type of 'x' and type of 'y'
>
> Is such idea already described somewhere?
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20171026/ee75b172/attachment.html>


More information about the Haskell-Cafe mailing list