[Haskell-cafe] Restrict values in type

Jake McArthur jake.mcarthur at gmail.com
Wed Jan 15 14:29:24 UTC 2014


This is what it should have been. Also, sorry for segmenting my emails.

data Stroke = Line Point Point (forall p. (Circle p, Rectangle p) => p)
            | Arc Point Point Point (forall p. Circle p => p)
            | Spot Point (forall p. PenShape p => p)
On Jan 15, 2014 9:26 AM, "Jake McArthur" <jake.mcarthur at gmail.com> wrote:

> 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/cdfad668/attachment.html>


More information about the Haskell-Cafe mailing list