How to model an entity with a currency? - f#

I am trying to model a bond entity in F# using a unit of measure for the currency.
type Bond = {
Isin: string
Issuer: string
Maturity: DateTime
Price: float<???>
}
Let's assume that a static table with all the available/possible currencies is available.
type Currency = {
Code : string
Name : string
}
I can go for Price as float and PriceCurrency as string or even as a Currency type but I think that this is not ideal.
Any ideas?

I don't think F# units of measure are a good match for this use case, since the compiler isn't aware of the currency table. If you want to use units of measure anyway, each currency would have to be hard-coded into your source, like this:
open System
[<Measure>] type Dollar
[<Measure>] type Pound
type Bond =
{
Isin: string
Issuer: string
Maturity: DateTime
}
type DollarBond =
{
Bond: Bond
Price: float<Dollar>
}
type PoundBond =
{
Bond: Bond
Price: float<Pound>
}
let poundsPerDollar = 0.73<Pound/Dollar>
let toPoundBond (dollarBond : DollarBond) =
{
Bond = dollarBond.Bond
Price = dollarBond.Price * poundsPerDollar
}
let dollarBond : DollarBond =
{
Bond = {
Isin = "My isin"
Issuer = "My issuer"
Maturity = DateTime.Parse("1/1/2050")
}
Price = 1000.0<Dollar>
}
printfn "%A" <| toPoundBond dollarBond

Related

ToString() override in F# doesn't work for a type containing another type

I have a type 'Team' which contains another type 'Employee'. I have overridden the ToString() for the type 'Employee'. However, when I do ToString() for the type 'Team', the details from 'Employee' is pretty-printed with the standard ToString() implementation and my overriding logic was never used. Can someone help understand why the override didn't work? Here is the code:
type Employee =
{
name : string
address : string
}
override this.ToString() = sprintf "Hello %s" this.name
type Team =
{
employee1 : Employee
}
with member this.ToTightString =
this.ToString().Replace(" ","")
let employee = { name="Bob"; address="Unknown"; }
let team = {employee1=employee}
printfn "%s" (employee.ToString()) // Override works!
// OUTPUT: Hello Bob
printfn "--------------------"
printf "%s" team.ToTightString // Override doesn't work
// OUTPUT: {employee1={name="Bob";address="Unknown";};}
As #rmunn has said above, the textual representation of a type (say, type1) specified in StructuredFormatDisplay is retained even if one calls ToString() on a type that contains the 'type1' type. Here's an example:
open System.Text.RegularExpressions
[<StructuredFormatDisplay("name=Always Harry address={address}")>]
type Employee =
{
name : string
address : string
}
type AddressContainer =
{
employee: Employee
containerName: string
}
let address1 = { name="Bob"; address="Random City" }
let addressContainer1 = { employee=address1; containerName= "container1"}
printf "%s" (address1.ToString()) // prints "name=Always Harry address=Random City"
printf "%s" (addressContainer1.ToString()) // prints {employee = name=Always Harry address=Random City; containerName = "container1";}

F# WebAPI default deserialization producing # sign

I'm working on an F# Web API application - https://github.com/odytrice/Dumia
When I try to send an Array of the following records,
[<CLIMutable>]
type Product =
{ ProductID : int
Code : string
Name : string
Price : decimal
ImageUrl : string }
[<CLIMutable>]
type Inventory =
{ Product: Product
Quantity: int }
Here is my current WebAPI Configuration
let registerWebApi (app:IAppBuilder) =
let config = new HttpConfiguration()
// Configure routing
config.MapHttpAttributeRoutes()
// Remove XML Formatter
config.Formatters.Clear()
let formatter = new JsonMediaTypeFormatter()
formatter.UseDataContractJsonSerializer <- false
config.Formatters.Add(formatter)
config.Services.Replace(typeof<IHttpControllerActivator>, CompositionRoot())
app.UseWebApi(config)
My Web API is producing the following output
{
Product#: {
ProductID#: 1,
Code#: "Bag-01",
Name#: "Ladies Bag",
Price#: 120,
ImageUrl#: "/content/images/bag.jpg"
},
Quantity#: 15
}
Does anyone have an idea how to get rid of the # sign?
The Problem is because of the Default DataContract used by WebAPI.
I had to change it to
config.Formatters
.JsonFormatter
.SerializerSettings
.ContractResolver
<- Serialization.DefaultContractResolver()
or better yet
config.Formatters
.JsonFormatter
.SerializerSettings
.ContractResolver
<- Serialization.CamelCasePropertyNamesContractResolver()

How to categorize over units of measure?

The problem is simple, I wish to do some calculations on some travel expenses which include both expenses in DKK and JPY. Thus I've found a nice way to model currency so I am able to convert back and forth:
[<Measure>] type JPY
[<Measure>] type DKK
type CurrencyRate<[<Measure>]'u, [<Measure>]'v> =
{ Rate: decimal<'u/'v>; Date: System.DateTime}
let sep10 = System.DateTime(2015,9,10)
let DKK_TO_JPY : CurrencyRate<JPY,DKK> =
{ Rate = (1773.65m<JPY> / 100m<DKK>); Date = sep10}
let JPY_TO_DKK : CurrencyRate<DKK,JPY> =
{ Rate = (5.36m<DKK> / 100.0m<JPY>); Date=sep10 }
I proceed to model expenses as a record type
type Expense<[<Measure>] 'a> = {
name: string
quantity: int
amount: decimal<'a>
}
and here I have an example list of expenses:
let travel_expenses = [
{ name = "flight tickets"; quantity = 1; amount = 5000m<DKK> }
{ name = "shinkansen ->"; quantity = 1; amount = 10000m<JPY> }
{ name = "shinkansen <-"; quantity = 1; amount = 10000m<JPY> }
]
And this is where the show stops... F# doesn't like that list, and complaints that all of the list should be DKK, -which of course makes sense.
Then I thought that there must be some smart way to make a discriminated union of my units of measures to put them in a category, and then I attempted with:
[<Measure>] type Currency = JPY | DKK
But this is not possible and results in The kind of the type specified by its attributes does not match the kind implied by its definition.
The solution I've come up with so far is very redundant, and I feel that it makes the unit of measure quite pointless.
type Money =
| DKK of decimal<DKK>
| JPY of decimal<JPY>
type Expense = {
name: string
quantity: int
amount: Money
}
let travel_expenses = [
{ name = "flight tickets"; quantity = 1; amount = DKK(5000m<DKK>) }
{ name = "shinkansen ->"; quantity = 1; amount = JPY(10000m<JPY>) }
{ name = "shinkansen <-"; quantity = 1; amount = JPY(10000m<JPY>) }
]
Is there a good way of working with these units of measures as categories? like for example
[<Measure>] Length = Meter | Feet
[<Measure>] Currency = JPY | DKK | USD
or should I remodel my problem and maybe not use units of measure?
Regarding the first question no, you can't but I think you don't need units of measures for that problem as you state in your second question.
Think how do you plan to get those records at runtime (user input, from a db, from a file, ...) and remember units of measures are a compile-time features, erased at runtime. Unless those records are always hardcoded, which will make your program useless.
My feeling is that you need to deal at run-time with those currencies and makes more sense to treat them as data.
Try for instance adding a field to Expense called currency:
type Expense = {
name: string
quantity: int
amount: decimal
currency: Currency
}
then
type CurrencyRate = {
currencyFrom: Currency
currencyTo: Currency
rate: decimal
date: System.DateTime}
As an alternative to Gustavo's accepted answer, If you still want to prevent anybody and any function accidentally summing JPY with DKK amounts, you can keep your idea of discriminated union like so :
let sep10 = System.DateTime(2015,9,10)
type Money =
| DKK of decimal
| JPY of decimal
type Expense = {
name: string
quantity: int
amount: Money
date : System.DateTime
}
type RatesTime = { JPY_TO_DKK : decimal ; DKK_TO_JPY : decimal ; Date : System.DateTime}
let rates_sep10Tosep12 = [
{ JPY_TO_DKK = 1773.65m ; DKK_TO_JPY = 5.36m ; Date = sep10}
{ JPY_TO_DKK = 1779.42m ; DKK_TO_JPY = 5.31m ; Date = sep10.AddDays(1.0)}
{ JPY_TO_DKK = 1776.07m ; DKK_TO_JPY = 5.33m ; Date = sep10.AddDays(2.0)}
]
let travel_expenses = [
{ name = "flight tickets"; quantity = 1; amount = DKK 5000m; date =sep10 }
{ name = "shinkansen ->"; quantity = 1; amount = JPY 10000m; date = sep10.AddDays(1.0)}
{ name = "shinkansen <-"; quantity = 1; amount = JPY 10000m ; date = sep10.AddDays(2.0)}
]
let IN_DKK (rt : RatesTime list) (e : Expense) =
let {name= _ ;quantity = _ ;amount = a ;date = d} = e
match a with
|DKK x -> x
|JPY y ->
let rtOfDate = List.tryFind (fun (x:RatesTime) -> x.Date = d) rt
match rtOfDate with
| Some r -> y * r.JPY_TO_DKK
| None -> failwith "no rate for period %A" d
let total_expenses_IN_DKK =
travel_expenses
|> List.fold(fun acc e -> (IN_DKK rates_sep10Tosep12 e) + acc) 0m
Even better would be to make function IN_DKK as a member of type Expense and put a restriction (private,...) on the field "amount".
Your initial idea of units of measure makes sense to prevent summing different currencies but unfortunately it does not prevent from converting from one to another and back to the first currency. And since your rates are not inverse (r * r' <> 1 as your data shows), unit of measure for currencies are dangerous and error prone. Note : I did not take into account the field "quantity" in my snippet.

Subtracting Records from a Set using case-insensitive comparison

I have a set of records:
type Person =
{
Name : string
Age : int
}
let oldPeople =
set [ { Name = "The Doctor"; Age = 1500 };
{ Name = "Yoda"; Age = 900 } ]
Unlike the hardcoded example above, the set of data actually comes from a data source (over which I have very little control). Now I need to subtract a set of data from another data source. In general, the data in this second source matches, but occasionally there is a difference in captialization:
let peopleWhoAreConfusedAboutTheirAge =
set [ { Name = "THE DOCTOR"; Age = 1500 } ]
When I attempt to subtract the second set from the first, it fails because the string comparison is case sensitive:
let peopleWhoKnowHowOldTheyAre =
oldPeople - peopleWhoAreConfusedAboutTheirAge
val peopleWhoKnowHowOldTheyAre : Set<Person> =
set [{Name = "The Doctor";
Age = 1500;}; {Name = "Yoda";
Age = 900;}]
Is there a way to perform a case-insensitive comparison for the Name field of the People record?
This is what I've implemented so far, though there may be a better way to do it.
My solution was to override the Equals function on the People record so as to perform a case-insensitive comparison. Set subtraction uses the Equals function to determine if two records match one another. By overriding Equals, I was forced (via warning and error) to override GetHashCode and implement IComparable (as well as set the CustomEquality and CustomComparison attributes):
[<CustomEquality; CustomComparison>]
type Person =
{
Name : string
Age : int
}
member private this._internalId =
this.Name.ToLower() + this.Age.ToString()
interface System.IComparable with
member this.CompareTo obj =
let other : Person = downcast obj
this._internalId.CompareTo( other._internalId )
override this.Equals( other ) =
match other with
| :? Person as other ->
System.String.Compare( this._internalId, other._internalId ) = 0
| _ -> false
override this.GetHashCode() =
this._internalId.GetHashCode()
This, however, seems to do the trick:
let oldPeople =
set [ { Name = "The Doctor"; Age = 1500 };
{ Name = "Yoda"; Age = 900 } ]
let peopleWhoAreConfusedAboutTheirAge =
set [ { Name = "THE DOCTOR"; Age = 1500 } ]
let peopleWhoKnowHowOldTheyAre =
oldPeople - peopleWhoAreConfusedAboutTheirAge
val peopleWhoKnowHowOldTheyAre : Set<Person> = set [{Name = "Yoda";
Age = 900;}]
If you know a better solution (involving less code), please post it rather than comment on this answer. I will happily accept a less verbose, awkward solution.
Here's another approach:
type Name(value) =
member val Value = value
override this.Equals(that) =
match that with
| :? Name as name -> StringComparer.CurrentCultureIgnoreCase.Equals(this.Value, name.Value)
| _ -> false
override this.GetHashCode() =
StringComparer.CurrentCultureIgnoreCase.GetHashCode(this.Value)
type Person =
{
Name: Name
Age: int
}
{Name=Name("John"); Age=21} = {Name=Name("john"); Age=21} //true

F# Records: Dangerous, only for limited use, or well used functionality?

So have gotten to record in my F# journey and at first they seem rather dangerous. At first this seemed clever:
type Card = { Name : string;
Phone : string;
Ok : bool }
let cardA = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
The idea that the cardA is patten matched with Card. Not to mention the simplified pattern matching here:
let withTrueOk =
list
|> Seq.filter
(function
| { Ok = true} -> true
| _ -> false
)
Problem is:
type Card = { Name : string;
Phone : string;
Ok : bool }
type CardTwo = { Name : string;
Phone : string;
Ok : bool }
let cardA = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
cardA is now of CardTwo type which I am guessing has to do with F# running everything in order.
Now this might be an impossible situation since there may never be a chance of the same signature taking on two type, but it is a possibility.
Is recording something that has only limited use or am I just over thinking this one?
They are not dangerous and they are not only for limited use.
I think it's very rare that you would have two types with the same members. But if you do encounter that situation, you can qualify the record type you want to use:
let cardA = { Card.Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
Records are very useful for creating (mostly) immutable data structures. And the fact that you can easily create a copy with just some fields changed is great too:
let cardB = { cardA with Ok = true }
I agree, record fields as members of the enclosing module/namespace seems odd at first coming from more traditional OO languages. But F# provides a fair amount of flexibility here. I think you'll find only contrived circumstances cause problems, such as two records that
are identical
have a subset/superset relationship
The first case should never happen. The latter could be solved by record B having a field of record A.
You only need one field to be different for the two to be distinguishable. Other than that, the definitions can be the same.
type Card =
{ Name : string
Phone: string
Ok : bool }
type CardTwo =
{ Name : string
Phone: string
Age : int }
let card = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
let cardTwo = { Name = "Alf" ; Phone = "(206) 555-0157" ; Age = 21 }
Pattern matching is also quite flexible as you only need to match on enough fields to distinguish it from other types.
let readCard card =
match card with
| { Ok = false } -> () //OK
| { Age = 21 } -> () //ERROR: 'card' already inferred as Card, but pattern implies CardTwo
Incidentally, your scenario is easily fixed with a type annotation:
let cardA : Card = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
In order that you appreciate what F# provides, I just want to mention that there is no fully qualified accessor for records in OCaml. Therefore, to distinguish between record types with the same fields, you have to put them into submodules and reference them using module prefixes.
So your situation in F# is much better. Any ambiguity between similar record types could be resolved quickly using record accessor:
type Card = { Name: string;
Phone: string;
Ok: bool }
type CardSmall = { Address: string;
Ok: bool }
let withTrueOk list =
list
|> Seq.filter (function
| { Card.Ok = true} -> true (* ambiguity could happen here *)
| _ -> false)
Moreover, F# record is not limited at all. It provides a lot of nice features out-of-the-box including pattern matching, default immutability, structural equality, etc.

Resources