Popularity
1.6
Stable
Activity
0.0
Stable
0
2
0

Monthly Downloads: 7
Programming language: Haskell
License: BSD 3-clause "New" or "Revised" License
Tags: Pattern

## Haskell pattern: cast

This pattern allows to incapsulate convert from one type of object for another.

## Example

Suppose you want convert different speed units to meter per second:

``````{-# LANGUAGE MultiParamTypeClasses #-}

import Pattern.Cast

newtype MeterPerSecond   = MeterPerSecond Float
deriving (Ord, Eq)
newtype KilometerPerHour = KilometerPerHour Float
newtype MilesPerHour     = MilesPerHour Float

instance Cast KilometerPerHour MeterPerSecond where
cast (KilometerPerHour v) = MeterPerSecond (0.277778 * v)

instance Cast MilesPerHour MeterPerSecond where
cast (MilesPerHour v) = MeterPerSecond (0.44704 * v)
``````

As you see, you have to use `MultiParamTypeClasses` language extension.

Then in every place you can just call one function `cast`:

``````> cast (KilometerPerHour 100) :: MeterPerSecond
MeterPerSecond 27.7778
> cast (MilesPerHour 100) :: MeterPerSecond
MeterPerSecond 44.704
``````

You can type your functions more abstractly. Let's look at this synthetic example:

``````type Second = Float
type Meter  = Float

data Aircraft = Aircraft { distance :: Meter
, time     :: Second
}

instance Cast Aircraft MeterPerSecond where
cast (Aircraft d t) = MeterPerSecond (d / t)
``````

Then you can use `Cast` in type of your fuction like this (`FlexibleContexts` extension has to be used):

``````{-# LANGUAGE FlexibleContexts #-}

slowerThenSound :: Cast a MeterPerSecond => a -> Bool
slowerThenSound x = cast x < MeterPerSecond 340.29
``````

And this fuction can be used with every type that can be converted in `MeterPerSecond`:

``````> slowerThenSound \$ MeterPerSecond 200
True
> slowerThenSound \$ KilometerPerHour 1000
True
> slowerThenSound \$ Aircraft 1200 3
False
``````