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:
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:
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 { ... }