The parametric type pattern

Parametric type is a core language feature that's used to materialize data types with parameters. It is a very powerful technique because the same object structure can be reused for different data types in its fields. In this section, we will demonstrate how parametric types can be applied effectively.

When designing applications, we often create composite types to conveniently hold multiple field elements. In its simplest form, composite types only serve as the containers of fields. As we create more and more composite types, it may become clear that some of these types look almost the same. Furthermore, the functions that operate on these types may be very similar as well. We could end up with a lot of boilerplate code. Wouldn't it be cool to have a template that allows us to customize a general composite type for a specific use? 

Consider a trading application that supports buying and selling stocks. In the very first version, we may have the following design:

Please beware that the notation in the preceding diagram may look a lot like Unified Modeling Language (UML). However, because Julia is not an object-oriented language, we may make certain exceptions when illustrating design concepts with these diagrams.

The corresponding code is as follows:

# Abstract type hierarchy for personal assets
abstract type Asset end
abstract type Investment <: Asset end
abstract type Equity <: Investment end

# Equity Instruments Types
struct Stock <: Equity
symbol::String
name::String
end

# Trading Types
abstract type Trade end

# Types (direction) of the trade
@enum LongShort Long Short

struct StockTrade <: Trade
type::LongShort
stock::Stock
quantity::Int
price::Float64
end

The data types we defined in the preceding code are fairly straightforward. The LongShort enum type is used to indicate the direction of trade—buying stock would be long, while selling stock would be short. The @enum macro is conveniently used to define the Long and Short constants.

Now, suppose that we were asked to support stock options in our next version of the software. Naively, we could define more data types, as follows:

The code is updated with additional data types, like so:

# Types of stock options
@enum CallPut Call Put

struct StockOption <: Equity
symbol::String
type::CallPut
strike::Float64
expiration::Date
end

struct StockOptionTrade <: Trade
type::LongShort
option::StockOption
quantity::Int
price::Float64
end

You might have noticed that the StockTrade and StockOptionTrade types are very similar. Such repetition is somewhat unsatisfying. It looks even worse when we define functions for these data types, as follows:

# Regardless of the instrument being traded, the direction of 
# trade (long/buy or short/sell) determines the sign of the
# payment amount.
sign(t::StockTrade) = t.type == Long ? 1 : -1
sign(t::StockOptionTrade) = t.type == Long ? 1 : -1

# market value of a trade is simply quantity times price
payment(t::StockTrade) = sign(t) * t.quantity * t.price
payment(t::StockOptionTrade) = sign(t) * t.quantity * t.price

Both the sign and payment methods are strikingly similar for both the StockTrade and StockOptionTrade types. Perhaps it isn't hard to imagine that this cannot scale very well when we add more tradable types to the application. There has to be a better way to do this. This is where the parametric type comes to the rescue!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.94.171