[Haskell-cafe] Restrict values in type
Nicolas Trangez
nicolas at incubaid.com
Wed Jan 15 14:13:46 UTC 2014
On Wed, 2014-01-15 at 13:55 +0000, Andras Slemmer wrote:
> > I have been looking at DataKinds and GADTs, but I can't quite figure out
> if they actually help me here at all.
> You are on the right track. With DataKinds and GADTs you can create an
> index type for PenShape:
>
> data Shape = Circle | Rectangle | Arbitrary
>
> data PenShape s where
> PenCircle :: Float -> PenShape Circle
> PenRectangle :: Float -> Float -> PenShape Rectangle
> ArbitraryPen :: PenShape Arbitrary
>
> You can use this index 's' to restrict PenShape to a particular
> constructor, or none at all:
>
> data Stroke where
> Spot :: Point -> PenShape s -> Stroke -- any shape allowed
> Arc :: Point -> Point -> Point -> PenShape Circle -> Stroke -- only
> circle
>
> In the Spot case the type variable 's' will be existentially hidden,
> meaning any type can go there.
>
> The tricky part comes when you want to have a notion of "or" in the case of
> Line. We basically need decidable type equality for this. Let's assume we
> have a way of deciding whether two lifted Shape types are equal and we get
> back a lifted Bool. Now we can write a type level "or" function:
>
> type family Or (a :: Bool) (b :: Bool) :: Bool
> type instance Or False False = False
> type instance Or True b = True
> type instance Or a True = True
>
> Now the Line case in the GADT would look something like this:
>
> Line :: Or (s :== Circle) (s :== Rectangle) ~ True => -- circle
> or rectangle
> Point -> Point -> PenShape s -> Stroke
>
> where :== is our type equality predicate. You can write this by hand if
> you'd like but it's pretty tedious and really should be inferred by the
> compiler or some automated process. And indeed the 'singletons' library
> does just this (and more), all you need to do is wrap your Shape definition
> in some th:
>
> $(singletons [d|data Shape = Circle | Rectangle | Arbitrary deriving (Eq)|])
>
> And voila you have a nice type safe datastructure:)
>
> A full module can be found here: http://lpaste.net/98527
I never used the 'singletons' library (yet), but since you're using it
already, can't what's provided by Data.Singletons.Bool (or
Data.Singletons.Prelude) be used instead of a hand-rolled type-level
bool?
Nicolas
More information about the Haskell-Cafe
mailing list