[Haskell-cafe] Creating a Point

Francesco Ariis fa-ml at ariis.it
Sat Jul 19 23:17:14 UTC 2014


On Sat, Jul 19, 2014 at 07:44:46PM -0300, Rafael Almeida wrote:
> I was talking to friends about how could you make a Point type in haskell.
> It's intuitive to make a 2D point such as:
> 
>     type Point2D = (Double, Double)
> 
> Using a list would be more general:
> 
>     type Point = [Double]
> 
> now we have a nice, general add function
> 
>     add = zipWith (+)
> 
> It's not so fun that we are able to do something like:
> 
>     add [2,3] [5,7,11]
> 
> We have no type-safety that we can only operate on points with the same
> dimension.
> 
> How could we address this? Can we make a general function, yet retain the
> type safety?

A possible solution /without/ using Template Haskell is using phantom types
for the various kind of |Point|s.
Example:

    data Point a = Point [Int] deriving (Show)

    data Two    -- data declaration sans constructors
    data Three

    crea2d :: Int -> Int -> Point Two
    crea2d a b = Point [a,b]

    crea3d :: Int -> Int -> Int -> Point Three
    crea3d a b c = Point [a,b,c]

    addPoints :: Point a -> Point a -> Point a
    addPoints (Point pa) (Point pb) = Point $ zipWith (+) pa pb


So you are sure addPoints is will only type-check on two similarly constructed
(i.e. same dimensions) |Point|s:

    ex2 = crea2d 1 2      -- make sure that "exSomething" is the only way to
    ex3 = crea3d 1 2 3    -- create Points (i.e. don't export Point(..))

    works = addPoints ex2 ex2
    stillworks = addPoints ex3 ex3
    doesntwork = addPoints ex2 ex3   -- won't type-check


Phantom types are a well known trick for "shifting" checks from run-time to
compile-time.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20140720/f3927e4d/attachment.sig>


More information about the Haskell-Cafe mailing list