Converting from m/s to km/h using F# Units of Measure - f#

I'm in the process of learning F# - and is currently looking into Units of Measure. I have a simple calculation returning meters per second, and I want to introduce a function converting it to kilometres per hour.
My code looks like this:
[<Measure>] type kg
[<Measure>] type s
[<Measure>] type m
[<Measure>] type km
[<Measure>] type h
let msToKmph(speed : float<m/s>) =
(float speed) * 3.6<km/h>
let gravityOnEarth = 9.81<m/s^2>
let heightOfJump = 3.5<m>
let speedOfImpact = sqrt (2.0 * gravityOnEarth * heightOfJump)
let speedOfImpactKmh = msToKmph(speedOfImpact)
This works - I get 8.28673639 m/s and 29.832251 km/h. What I am unsure of is if this is the best way to express the relationship between different units. Can this be done more elegantly?
For instance, the line doing (float speed) to remove the unit information from the speed parameter, to make the msToKmph return km/h. If I did not remove unit information before doing the calculation, the returned unit would be: km m/(h s)

First, your msToKmph is totally incorrect. Although it returns a correct return value, what it is actually doing, is it just drops the original <m/s> value by converting to a plain, measureless float and then multiplies the measureless value to a 3.6<km/h>.
To better express the relations between UoM's, consider this:
let kmToM = 1000.0<m/km> // relation between kilometers and meters
let hrToSec = 3600.0<s/h> // relation between seconds and hours
let msToKmph(speed : float<m/s>) =
speed / kmToM * hrToSec
Note, all "magic numbers" are encapsulated within UoM converters, hence your formulas remain clean, e.g. they simply operate values and constants, but the UoM are calculated by the compiler.
Update: The philosophy of UoM conversion is that the conversion formulas should be something that has physical sense. The rule of thumb is whether your conversion value presents in reference books. In plain English, 3.6<km/h> from above is useless, but 1000.0<m/km> just says, "there is 1000 m in 1 km", which makes sense.
You can even improve hrToSec like this:
let hrToSec2 = 60.0<s/minute> * 60.0<minute/h>
This will make every value a well-known value found in reference books.

You're right that removing unit information is a bad thing. You should create a few constants with appropriate units for conversion.
let mPerKm = 1000.0<m/km>
let secondPerHour = 3600.0<s/h>
// val msToKmph : float<m/s> -> float<km/h>
let msToKmph(speed : float<m/s>) =
speed / mPerKm * secondPerHour
For km and m, a generic solution is to define a unit prefix k so it works for many UoMs which have kilo as a metric:
[<Measure>] type k
let kilo = 1000.0<1/k>
let secondPerHour = 3600.0<s/h>
// val msToKmph : float<m/s> -> float<k m/h>
let msToKmph(speed : float<m/s>) =
speed / kilo * secondPerHour

Related

Types vs. Modules in F#

The answer on Confused about static dictionary in a type, in F# finished with one advice: and just in general: try to use fewer classes and more modules and functions; they're more idiomatic in F# and lead to fewer problems in general
Which is a great point, but my 30 years of OO just don't want to give up classes just yet (although I was fighting against C++ like crazy when we moved away from C...)
so let's take a practical real world object:
type Currency =
{
Ticker: string
Symbol: char
}
and MarginBracket =
{
MinSize: decimal
MaxSize: decimal
Leverage: int
InitialMargin: decimal
MaintenanceMargin: decimal
}
and Instrument =
{
Ticker: string
QuantityTickSize: int
PriceTickSize: int
BaseCurrency: Currency
QuoteCurrency: Currency
MinQuantity: decimal
MaxQuantity: decimal
MaxPriceMultiplier: decimal
MinPriceMultiplier: decimal
MarginBrackets: MarginBracket array
}
// formatting
static member private formatValueNoSign (precision: int) (value: decimal) =
let zeros = String.replicate precision "0"
String.Format($"{{0:#.%s{zeros}}}", value)
static member private formatValueSign (precision: int) (value: decimal) =
let zeros = String.replicate precision "0"
String.Format($"{{0:+#.%s{zeros};-#.%s{zeros}; 0.%s{zeros}}}", value)
member this.BaseSymbol = this.BaseCurrency.Symbol
member this.QuoteSymbol = this.QuoteCurrency.Symbol
member this.QuantityToString (quantity) = $"{this.BaseSymbol}{Instrument.formatValueSign this.QuantityTickSize quantity}"
member this.PriceToString (price) = $"{this.QuoteSymbol}{Instrument.formatValueNoSign this.PriceTickSize price}"
member this.SignedPriceToString (price) = $"{this.QuoteSymbol}{Instrument.formatValueSign this.PriceTickSize price}"
member this.RoundQuantity (quantity: decimal) = Math.Round (quantity, this.QuantityTickSize)
member this.RoundPrice (price : decimal) = Math.Round (price, this.PriceTickSize)
// price deviation allowed from instrument price
member this.LowAllowedPriceDeviation (basePrice: decimal) = this.MinPriceMultiplier * basePrice
member this.HighAllowedPriceDeviation (basePrice: decimal) = this.MaxPriceMultiplier * basePrice
module Instrument =
let private allInstruments = Dictionary<string, Instrument>()
let list () = allInstruments.Values
let register (instrument) = allInstruments.[instrument.Ticker] <- instrument
let exists (ticker: string) = allInstruments.ContainsKey (ticker.ToUpper())
let find (ticker: string) = allInstruments.[ticker.ToUpper()]
In this example, there is an Instrument object with its data and a few helper members and a module which acts as a repository when it's time to find an object by name (a trading ticker in this case, so they're known and formatted, it's not a random string)
I could move the helping member to the module, for example:
member this.LowAllowedPriceDeviation (basePrice: decimal) = this.MinPriceMultiplier * basePrice
could become:
let lowAllowedPriceDeviation basePrice instrument = instrument.MinPriceMultiplier * basePrice
So the object would become simpler and could eventually be turned into a simple storage type without any augmentations.
But I am wondering what are the practical benefits (let's just consider readability, maintainability, etc)?
Also, I don't see how this could be re-structured to not be a class, short of having an 'internal' class in the module and doing all operations through that, but that would just be shifting it.
Your intuition about turning LowAllowedPriceDeviation to a module is correct: it could become a function with the this parameter moved to the end. That is an accepted pattern.
Same goes for all other methods on the Instrument type. And the two private static methods could be come private functions in the module. The exact same approach.
The question "how this could be re-structured to not be a class" confuses me a bit, because this is not actually a class. Instrument is a record, not a class. The fact that you gave it some instance and static methods doesn't make it a class.
And finally (though, technically, this part is opinion-based), regarding "what are the practical benefits" - the answer is "composability". Functions can compose in the way that methods can't.
For example, say you wanted a way to print multiple instruments:
let printAll toString = List.iter (printfn "%s" << toString)
See how it's parametrized with a toString function? That's because I'd like to use it for printing instruments in different ways. For example, I might print their prices:
printAll priceToString (list())
But if PriceToString is a method, I'd have to introduce an anonymous function:
printAll (fun i -> i.PriceToString) (list())
This looks just a little bit more involved than using a function, but in practice it gets very complicated fast. A bigger problem, however, is that this wouldn't even compile because type inference doesn't work on properties (because it can't). In order to get it to compile, you have to add a type annotation, making it even uglier:
printAll (fun (i: Instrument) -> i.PriceToString) (list())
That's just one example of function composability, there are many others. But I'd rather not write a whole blog post on this subject, it's already much longer than I'd like.

Records vs Single-Case Discriminated Unions

What are the Pro's and Con's of using either
type Complex =
{
real: float;
imag: float;
}
or
type Complex =
Complex of
real: float *
imag: float
I am particularly interested in readability and handling in different situations.
And to a lesser extent, performance.
Using helper functions you could get the same out of both approaches.
Record
type ComplexRec =
{
real: float
imag: float
}
// Conciseness
let buildRec(r,i) =
{ real = r ; imag = i }
let c = buildRec(1.,5.)
// Built-in field acces
c.imag
Union type
type ComplexUnion =
Complex of
real: float * imag: float
// Built-in conciseness
let c = Complex(1.,5.)
// Get field - Could be implemented as members for a more OO feel
let getImag = function
Complex(_,i) -> i
getImag c
I imagine the (frequent) decomposition of the union type could influence performance, but I'm no expert on the subject.
In case of the record type, let's say that you declared symbol it : Complex you have immediate access to both fields like: it.real, it.imag
In the case of discriminated union (DU) you have to first unpack DU type like:
match it with
| Complex (real, imag) -> real, imag
DU makes sense when you have some choices on the type. Your Complex type doesn't branch to few cases, it only has one possible shape, case.
In this case I'm in favour of record type as it gives more readable code in usage.

What is the difference between float32 vs single and float vs double, if any?

I have always considered the types float32 and single to be interchangeable, in that they are type aliases. The same for float and double. However, they appear to be declared in different assemblies Microsoft.FSharp.Core.Operators vs Microsoft.FSharp.Core.ExtraTopLevelOperators.
Also, the popup description is slightly different, where F# says on float32 and float that it can take a string and use Parse() on it.
However, trying that with single and double succeeds just fine too:
let x = single "12.3"
let y = double "13.4"
Is there any difference I should be aware of? I have always used them interchangeably, never really gave it another thought, until I saw the differences in the popups and in signatures:
// on hovering, or in FSI, this will have the slightly confusing signature:
// val x: a: double -> float
let x (a: double) = float a
All of them are just aliases of the corresponding CLR types as you can see in prim-types-prelude.fs.
type float32 = System.Single
type float = System.Double
type single = System.Single
type double = System.Double
As for the confusing signature consider this:
type typA = A;;
type typB = typA;;
let f (x : typA) = (x : typB)
//val f : x:typA -> typB
Seems like F# prefers to use the aliases at the places you (or some other definition) used them.
Finally the namespaces you are referring to (FSharp.Core.Operators) are referring not to the float type but the float function (float : 'T -> float). See prim-types.fs.

index rows by year in F#

i am reading my data as a frame on F# as follows
let myannual = Frame.ReadCsv("data/annual.csv")
My frame consists of time series columns and a year column, and I would like to index my time series by year. I cannot do it as follows
let myyears = [| for i in myannual.GetColumn<float>("yyyy").Values -> float i |]
let myindexedframe = myannual.IndexRows(myyears)
What should I do? Any feedback is appreciated!
The ReadCsv method takes an optional parameter indexCol that can be used to specify the index column - and you also need to provide a type parameter to tell Deedle what is the type of the index:
let myannual = Frame.ReadCsv<int>("data/annual.csv", indexCol="yyy")
Your approach would work too, but you'd need to use IndexRowsWith, which takes a sequence of new indices (and it is better to use int because float is imprecise for years):
let myyears = [| for i in myannual.GetColumn<float>("yyyy").Values -> int i |]
let myindexedframe = myannual.IndexRowsWith(myyears)
The IndexRows method takes just the name of a column (very similar to using the indexCol parameter when calling ReadCsv):
let myindexedframe = myannual.IndexRows<int>("yyyy")

arithmetic within string literal in Swift

Playing with Swift, I found something awkward error.
let cost = 82.5
let tip = 18.0
let str = "Your total cost will be \(cost + tip)"
This works fine as I expect, but
let cost = 82.5
let tip:Float = 18
let str = "Your total cost will be \(cost + tip)"
would not work with error
could not find member 'convertFromStringInterpolationSegment'
let str = "Your total cost will be \(cost + tip)"
The difference between two example is declaring tip constant to explicitly float or not. Would this be reasonable result?
You still need to cast the numbers into the same type so they can be added together, e.g:
let cost = 82.5
let tip:Float = 18
let str = "Your total cost will be \(Float(cost) + tip)"
By default real number literals are inferred as Double, i.e:
let cost:Double = 82.5
So they need to be either explicitly cast to a Double or a Float to be added together.
Values are never implicitly converted to another type.
let cost = 82.5
let tip:Float = 18
let str = "Your total cost will be \(cost + tip)"
In the above example it is considering cost as double & you have defined tip as float, so it is giving error.
Rather specify the type of cost as float as shown below
let cost:Float = 82.5
Hope it will solve your problem.
In your code cost in inferred to be of type Double.
In your first (working) example tip is also inferred to be Double and the expressions cost + tip is an addition of two Double values, resulting in a Double value.
In your second (not working) example tip is declared to be Float therefore the expressions cost + tip is an error.
The error message is not very informative. But the problem is that you are adding a Double to a Float and in a strongly statically typed language you will not have automatic type conversions like you had in C or Objective C.
You have to do either Float(cost) + tip or cost + Double(tip)

Resources