[Haskell-cafe] Restrict values in type

Luke Clifton ltclifton at gmail.com
Thu Jan 16 02:07:44 UTC 2014


Well that works wonderfully for parts of the problem.

listOfStrokes = [ Line point point (circle 5)
                , Line point point (rectangle 2 3)
                , Arc point point point (circle 2)
                , Spot point arbitraryPen
                , Spot point (circle 1)
                , Spot point (rectangle 1 1)
                ]


*Tmp> :t listOfStrokes
listOfStrokes :: [Stroke]

But how can I extract the information about the PenShape from such a
structure?

I can't pattern match (unless there is some language extension I am
missing).

case Arc point point point (circle 1) of
    (Arc _ _ _ (circle r)) -> r

<interactive>:67:14: Parse error in pattern: circle

This seems obvious to me because pattern matching works on data
constructors (though I have often found that what I think is obvious is not
always correct...). This would leave me to believe that, because there are
no data constructors for Circle, Rectangle and PenShape that I couldn't
pattern match on it.

I tried to add some functions to the various classes to figure it out, but
that didn't seem to take me anywhere.






On Wed, Jan 15, 2014 at 10:29 PM, Jake McArthur <jake.mcarthur at gmail.com>wrote:

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


More information about the Haskell-Cafe mailing list