[Haskell-cafe] Restrict values in type

Jake McArthur jake.mcarthur at gmail.com
Wed Jan 15 14:26:19 UTC 2014


Sorry, I used existential types but should have used universal types.
On Jan 15, 2014 9:25 AM, "Jake McArthur" <jake.mcarthur at gmail.com> wrote:

> You can get some kind of subtyping out of type classes. Then it's just a
> matter of making a few different instances so you can do what you want with
> them.
>
> class Circle a where
>   circle :: Float -> a
>
> class Rectangle a where
>   rectangle :: Float -> Float -> a
>
> class (Circle a, Rectangle a) => PenShape a where
>   arbitraryPen :: ... -> a
>
> data Stroke = forall p. (Circle p, Rectangle p) => Line Point Point p
>             | forall p. Circle p => Arc Point Point Point p
>             | forall p. PenShape p => Spot Point p
>
> - Jake
> Hi,
>
> I'm quite new to Haskell, and have been loving exploring it. I've always
> been a huge fan of languages that let me catch errors at compile time,
> finding dynamic languages like Python a nightmare to work in. I'm finding
> with Haskell I can take this compile time checking even further than most
> static languages and it has gotten me rather excited. So I was wondering if
> there is a Haskell way of solving my problem.
>
> I'm trying to represent an image made up of a list of strokes. Strokes are
> either lines, arcs or spots, and can be made using different pen shapes.
>
> data Image = Image [Stroke]
>
> data Stroke = Line Point Point PenShape
>     | Arc Point Point Point PenShape
>     | Spot Point PenShape
>
> data PenShape = Circle Float
>     | Rectangle Float Float
>     | ArbitraryPen -- Stuff (not relevant)
>
> And this is all great and works.
>
> But now I have a problem. I want to extend this such that Arc strokes are
> only allowed to have the Circle pen shape, and Lines are only allowed to
> have the Rectangle or Circle pen shapes.
>
> What is the best way of enforcing this in the type system.
>
> I could make more Strokes like LineCircle, LineRectangle, Arc,
> PointCircle, PointRectangle, PointArbitrary and get rid of the PenShape
> type altogether. But this doesn't really feel good to me (and seems like
> the amount of work I have to do is bigger than it needs to be, especially
> if I added more basic pen shapes).
>
> I thought about making the different PenShapes different types, using
> typeclasses and making Stroke an algebraic data type, but then my strokes
> would be of different types, and I wouldn't be able to have a list of
> strokes.
>
> I have been looking at DataKinds and GADTs, but I can't quite figure out
> if they actually help me here at all.
>
> I'm sure there is a way to do this, I'm just not googling properly.
>
> What I want to write is...
>
> data Image = Image [Stroke]
>
> data Stroke = Line Point Point (Circle or Rectangle)
>     | Arc Point Point Point Circle
>     | Spot Point PenShape
>
> data PenShape = Circle Float
>     | Rectangle Float Float
>     | ArbitraryPen -- Stuff (not relevant)
>
> Regards,
>
> Luke
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20140115/00d271e3/attachment.html>


More information about the Haskell-Cafe mailing list