[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