[Haskell-cafe] Restrict values in type

Jake McArthur jake.mcarthur at gmail.com
Wed Jan 15 14:25:33 UTC 2014


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


More information about the Haskell-Cafe mailing list