<div><div dir="auto">Welcome! You can certainly express the constraint you want. But you can't do what you're trying to do with ShapeBox. </div><div dir="auto"><br></div><div dir="auto">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. </div><div dir="auto"><br></div><div dir="auto">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:</div><div dir="auto"><br></div><div dir="auto"> bar :: ShapeBox -> ShapeBox -> Bool</div><div dir="auto"> bar (ShapeBox x) (ShapeBox y) = intersect x y</div><div dir="auto"><br></div><div dir="auto">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. </div><div dir="auto"><br></div><div dir="auto">But there's hope. The way to declare the constraint you're after is to put it on the instance declaration:</div><div dir="auto"><br></div><div dir="auto"> instance (Shape a, Shape b) => Intersect a b where</div><div dir="auto"> intersect x y = ...</div><div dir="auto"><br></div><div dir="auto">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. </div><div dir="auto"><br></div><div dir="auto">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."</div><div dir="auto"><br></div><div dir="auto">You may want to check out the diagrams package, which does something similar with the class HasEnvelope. </div><div dir="auto"><br></div><div dir="auto">Hope that helps,</div><div dir="auto"><br></div><div dir="auto">Ben</div><br><div class="gmail_quote"><div>On Thu, Oct 26, 2017 at 11:37 AM Tomasz Chronowski <<a href="mailto:chronowski.tomasz@gmail.com">chronowski.tomasz@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><span style="font-size:12.8px">This is my first post here, so Hello everyone!</span><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">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'":</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px"><font face="monospace, monospace">class (A a, B b) => AB a b ...</font></div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">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'"?</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">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 <span style="font-size:12.8px">in a "Object Oriented" way:</span></div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px"><font face="monospace, monospace">data Circle = Circle { ... }</font></div><div style="font-size:12.8px"><font face="monospace, monospace">data Square = Square { ... }</font></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><font face="monospace, monospace">class Shape a</font></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><font face="monospace, monospace">class Intersect a b where</font></div><div style="font-size:12.8px"><font face="monospace, monospace"> intersect :: a -> b -> Bool</font></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><div><font face="monospace, monospace">-- pseudo haskell - "If 'a' is instance of 'Shape' and 'b' is instance of 'Shape' then 'a' and 'b' are instance of 'Intersect'"<br></font></div><div><font face="monospace, monospace">-- maybe some type hackery allows to express this?</font></div><div><font face="monospace, monospace">constraint Shape a, Shape b => Intersect a b</font></div></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><font face="monospace, monospace">instance Shape Circle</font></div><div style="font-size:12.8px"><font face="monospace, monospace">instance Shape Square</font></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><font face="monospace, monospace">instance Intersect Circle Circle ...</font></div><div style="font-size:12.8px"><font face="monospace, monospace">instance Intersect Circle Square ...<br></font></div><div style="font-size:12.8px"><font face="monospace, monospace">...</font></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><font face="monospace, monospace">data ShapeBox = forall a. Shape a => </font><span style="font-family:monospace,monospace;font-size:12.8px">ShapeBox</span><font face="monospace, monospace"> a</font></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><font face="monospace, monospace">foo = let x:y:_ = [</font><span style="font-family:monospace,monospace;font-size:12.8px">ShapeBox</span><font face="monospace, monospace"> Circle { ... }, </font><span style="font-family:monospace,monospace;font-size:12.8px">ShapeBox</span><font face="monospace, monospace"> Square { ... }, ...]</font></div><div style="font-size:12.8px"><font face="monospace, monospace"> 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'</font></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><font face="arial, helvetica, sans-serif">Is such idea already described somewhere?</font></div></div>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</blockquote></div></div>