This is example code as suggested on FunctionalModeling. Code collected by ShaeErisson
module Truck where
-- http://c2.com/cgi-bin/wiki?FunctionalModeling
-- 1. truck and tire as types
-- we alias Pressure to Integer here, following the OnceAndOnlyOnce principle
type Pressure = Integer
-- tire as unification type
data Tires = Michelin Pressure | Pirelli Pressure
checkPressure :: Tires -> Pressure
checkPressure (Michelin pressure) = pressure
checkPressure (Pirelli pressure) = pressure
{-
interactively:
*Truck> let x = Pirelli 5
*Truck> checkPressure x
5
-},
-- 2. tire as typeclass
-- a typeclass describes an operation
-- any type can provide an implementation of this operation
class Tire a where
getPressure :: a -> Pressure
-- some random type
data MyFoo = Foo Pressure deriving (Show, Eq)
instance Tire MyFoo where
getPressure (Foo a) = a
{-
interactively:
*Truck> let y = Foo 5
*Truck> getPressure y
5
-},
-- 3. unified type with records
-- from HalDaume III
-- a record is ... well.. like a database record sort of...
data Tires' = Michelin' { checkPressure' :: Pressure }, | Pirelli' { checkPressure' :: Pressure },
-- 4. alternate tire typeclasses
-- from EsaPulkkinen
class Tire' a where
createTire' :: Pressure -> a
getPressure' :: a -> Pressure
-- Esa: This will cause some problems for the user
-- Esa: he has to choose a representation
-- Esa: that is, getPressure (createTire x) does not work.
-- another idea is to use a factory to build tires
class Tire'' a where
getPressure'' :: a -> Pressure
class TireFactory'' f where
createTire :: Tire'' a => f a -> Pressure -> a
data MyTireFactory a = MyTireFactory { myTireFromPressure :: Pressure -> a },
data MyTire = MyTire { myTirePressure :: Pressure },
myTireFactory :: MyTireFactory MyTire
myTireFactory = MyTireFactory (\p -> MyTire p)
instance TireFactory'' MyTireFactory where
createTire (MyTireFactory f) p = f p
instance Tire'' MyTire where
getPressure = myTirePressure
-- Esa: you could embed Pressure in the factory as well
-- Esa: so that constructing factory will be the place where the pressure is required.
-- Esa: you could have a design where a car encloses all tire and pressure handling
class Car c t where
getTires :: c -> [t]
getPressure :: c -> t -> Pressure
class Car' c where
getTires :: c t -> [t]
getPressure :: c t -> t -> Pressure
-- Esa: but that has a problem that it does not properly describe
-- Esa: the connection between a tire and a car
-- Esa: [or you have to handle error cases
-- Esa: where you ask a pressure from a tire
-- Esa: that is not in the same car that you specified]
-- Esa: Another alternative is to represent this using a mapping from cars to tires:
class CarTireMapping m where
getTires :: m c t -> c -> [t]
getPressure :: m c t -> t -> Pressure
-- Truck class using functional dependencies
-- from AndrewBromage (under construction)
-- class Truck truck tyre | truck -> tyre where { ... },