Q:

Getting Haskell to Distinguish Type Synonyms

I like the idea of Haskell type synonyms, because they allow for distinguishing between abstract datatypes that share underlying representations. Unfortunately, when I write a program like
data Vector a = Vec a a

-- Some definitions here about (+) and (*) for Vector ...

type Position = Vector Float
type Velocity = Vector Float
type Time = Float

step :: Position -> Velocity -> Time -> Position
step p v dt = p + v*dt

p :: Position
p = Vec 0.0 0.0

v :: Velocity
v = Vec 1.0 1.0

p' = step v p 0.01

This is perfectly valid Haskell code, despite v and p being in the wrong spots. I would like to strengthen the distinction between type synonyms, such that they still share underlying representation, but are not accepted as each other in function application. Is this possible?

A:

newtype is likely what you want, or at any rate, the best we've got.  Like type, it defines a new name for an existing type, and the runtime representation will be the same.  Unlike type (but like data), they are considered different during type checking, and there is a new data constructor.
So you might have code like:
newtype Position = Position (Vector Float)
p :: Position
p = Position (Vec 0 0)

A:

You could make Vector a phantom type as follows:
data Vector t a = Vec a a

data Pos
data Vel

type Position = Vector Pos Float
type Velocity = Vector Vel Float

Now, you can define instances of Position and Velocity like you'd normally do:
p :: Position
p = Vec 0.0 0.0

v :: Velocity
v = Vec 1.0 1.0

However, it won't allow you to use them interchangeably:
type Time = Float

step :: Position -> Velocity -> Time -> Position
step p v dt = p + v*dt -- you might have to change this definition

p' = step v p 0.01 -- won't compile

You can also make things more precise by using DataKinds and KindSignatures:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}

data VectorType = Pos | Vel

data Vector (t :: VectorType) a = Vec a a

type Position = Vector Pos Float
type Velocity = Vector Vel Float

Hope that helps.

