Functional Modeling Examples

last modified: November 5, 2011

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

Loading...