Last active
January 21, 2020 13:55
-
-
Save schicks/a68a7f44796fbd6dbfc3d98485f25b90 to your computer and use it in GitHub Desktop.
Types are Boring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* | |
* A linear algebra approach to the problem described here: | |
* https://alexnixon.github.io/2020/01/14/static-types-are-dangerous.html | |
*) | |
type currency = (* Currencies as a simple enum *) | |
| GBP | |
| USD | |
| JPY | |
type currency_value = (currency * int) list (* Values as a vector, with currencies as an eigenbasis *) | |
let ($*) s = List.map(function | currency, v -> currency, v * s) (* Scalar multiplication *) | |
let ($+) (a: currency_value) (b: currency_value) = (* Vector addition *) | |
let result = (List.map (fun a -> match a with | |
| currency, u -> match List.assoc_opt currency b with | |
| None -> (currency, u) | |
| Some(v) -> (currency, u + v)) | |
a | |
) in | |
List.fold_left | |
(fun acc a -> match a with | |
| currency, u -> match List.assoc_opt currency result with | |
| None -> (currency, u)::acc | Some(_) -> acc) | |
result | |
b | |
let notionally trades = | |
List.map (function | cv, s, _ -> cv, s) trades | |
|> List.fold_left | |
(fun acc a -> match a with | |
| cv, s -> acc $+ (s $* cv) | |
) | |
[] | |
let trades = [ | |
[GBP, 1], 100, "VOD.L"; | |
[GBP, 2], 200, "VOD.L"; | |
[USD, 3], 300, "AAPL.O"; | |
[JPY, 5], 50, "4151.T"; | |
] | |
let result = notionally trades |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@fried_brice pointed out that this does not quite meet the requirements as described by Alex. Part of the problem was that the display function as Alex is taking it should take a scalar value (just an integer) rather than a currency vector, and this code addresses that. But the other part of the requirement, which is not addressed as well, is that a given trade should have one and only one currency. The code as written doesn't quite do that, but it's fairly easy to get to;
Now we have an explicit concept of a trade which is specific to a currency, and can trivially map it back up into a currency vector.