F# Units of Measurement modeling metric prefix (micro, milli, nano) - f#

As per this question: Fractional power of units of measures in F# there are no fractional powers supported for units of measure in F#.
In my application, it is beneficial to think of data with a metric prefix sometime, e.g. when dealing with seconds. Sometimes I need a result in milli-seconds, sometimes in seconds.
The alternative I'm currently thinking about using is this
[<Measure>] type milli
[<Measure>] type second
let a = 10.0<second>;
let b = 10.0<milli*second>
which gives me:
val a : float<second> = 10.0
val b : float<milli second> = 10.0
Now I want to allow calculations with the two operations. So I could do
let milliSecondsPerSecond = 1000.0<(milli*second)/second>
let a = 10.0<second>;
let b = 10.0<milli*second>
(a*milliSecondsPerSecond) + b
which gives me exactly what I wanted
val it : float<milli second> = 10010.0
Now, this is all nice and shiny but grows out of hand quickly when you want to support multiple units and multiple prefixes. So I think it would be either necessary to bake this into a more generic solution, but don't know where to start. I tried
let milliPer<'a> = 1000.0<(milli * 'a) / 'a>
but that won't work because f# complains and tells me "Non-Zero constants cannot have generic units"...
Since I imagine that unit prefixes are a common problem, I imagine someone has solved this problem before. Is there a more idiomatic way to do unit prefixes in F#?

You write the constant as 1000.0<(milli second)/second> representing 1000 milliseconds per second, but actually (you can do this as an algebraic simplification) "milli" just means that you need to multiply whatever unit by 1000 to get the unit without the "milli" prefix.
So, you can simplify your definition of milliPer (and milliSecondsPerSecond) to just say:
let milli = 1000.0<milli>
Then it is possible to use it with other kinds of measures:
(10.0<second> * milli) + 10.0<milli second>
(10.0<meter> * milli) + 10.0<milli meter>
I think this should not lead to any complications anywhere in the code - it is a perfectly fine pattern when working with units (I've seen people using a unit of percentsimilarly, but then the conversion is 0.01)

Related

How to generalise printing measure [duplicate]

I am beginning to learn how to use units of measure in F# but I haven't found the answer to this simple question yet. How do you print the resultant units after a calculation. I know that FSI prints them so they should be available somehow.
For example:
[<Measure>] type m;;
[<Measure>] type s;;
let d = 10<m>;;
val d : int<m> = 10
let t = 2<s>;;
val t : int<s> = 2
I want to do something like this:
printfn "Results: %A %A" (d / t) (UOM (d / t));;
"Results: 5 m/s"
Thanks in advance
Unfortunately, this is not possible.
Units of measure exist only at compile time. When you compile the program, they will be ereased (because .NET doesn't have any way of representing units for types). This means that at the runtime, the result of your calculation will be just float. I don't think there is any way other than just writing units as string in your code...
There was a related question some time ago. It has some more details and also explains why you cannot get information about units using reflection.
Why can not use reflection in f#

F# / Simplest way to validate array length at COMPILE time

I have some scientific project. There are vectors / square matrices of various lengths there. Obviously (for example) a vector of length 2 cannot be added to a vector of length 3 (and so on and so forth). There are several NET libraries, which deal with vectors / matrices. All of them either have generic vectors / matrices OR have some very specific vectors / matrices, which do not suite the needs.
Most, if not all, of these libraries can create a vector from a list or array. Unfortunately, If I mistakenly give an input array of the wrong length, then I will get a vector of the wrong length and then everything will blow up at run time!
I wonder if it is possible to check array length at compile time so that to get a compile error if, let’s say, I try to pass a 5-element array to a vector of length 2 “constructor”. After all, printfn does almost that!
F# type providers come to mind, but I am not sure how to apply them here.
Thanks a lot!
Thanks to the OP for an interesting question. My answer frequency has dropped not because of unwillingness to help but rather that there a few questions that tickles my interest.
We don't have dependent types in F# and F# doesn't support generics with numerical type arguments (like C++).
However we could create distinct types for different dimensions like Dim1, Dim2 and so on and provide them as type arguments.
This would allow us to have a type signature for apply that applies a vector a matrix like this:
let apply (m : Matrix<'R, 'C>) (v : Vector<'C>) : Vector<'R> = …
The code won't compile unless the columns of the matrix matches the length of the vector. In addition; the resulting vector has the length that is rows of the columns.
One way to do this is defining an interface IDimension and some concrete implementions representing the different dimensions.
type IDimension =
interface
abstract Size : int
end
type Dim1 () = class interface IDimension with member x.Size = 1 end end
type Dim2 () = class interface IDimension with member x.Size = 2 end end
The vector and the matrix can then be implemented like this
type Vector<'Dim when 'Dim :> IDimension
and 'Dim : (new : unit -> 'Dim)
> () =
class
let dim = new 'Dim()
let vs = Array.zeroCreate<float> dim.Size
member x.Dim = dim
member x.Values = vs
end
type Matrix<'RowDim, 'ColumnDim when 'RowDim :> IDimension
and 'RowDim : (new : unit -> 'RowDim)
and 'ColumnDim :> IDimension
and 'ColumnDim : (new : unit -> 'ColumnDim)
> () =
class
let rowDim = new 'RowDim()
let columnDim = new 'ColumnDim()
let vs = Array.zeroCreate<float> (rowDim.Size*columnDim.Size)
member x.RowDim = rowDim
member x.ColumnDim = columnDim
member x.Values = vs
end
Finally this allows us to write code like this:
let m76 = Matrix<Dim7, Dim6> ()
let v6 = Vector<Dim6> ()
let v7 = apply m76 v6 // Vector<Dim7>
// Doesn't compile because v7 has the wrong dimension
let vv = apply m76 v7
If you need a wide range of dimensions (because you have an algebra increments/decrements the dimensions of vectors/matrices) you could support that using some smart variant of church numerals.
If this is usable or not is entirely up the reader I think.
PS.
Perhaps unit of measures could have been used for this as well if they applied to more types than floats.
The general term for what you're looking for is dependent types, but F# does not support them.
I've seen an experiment in using type providers to mimic one particular flavor of dependent types (constraining the domain of a primitive type), but I wouldn't expect it to be possible to achieve what you want using type providers in their current form. They seem to be too whimsical for that.
Print format strings appear to be doing that (and in fact printers are a "Hello World" application for dependent types), but actually they work because they get special treatment by the compiler, and the mechanism for that is not extensible.
You're doomed to ensure correct lengths at runtime.
My best bet would be to use structs to encode actual vectors and ensure correctness on the API level that way, map them to arrays at the point where you're interacting with those matrix algebra libraries, then map the results back to structs with ample assertions when done.
The comment from #Justanothermetaprogrammer qualifies as an answer. Here is how it works in the real example. The matrix implementation in the example is based on MathNet.Numerics.LinearAlgebra:
open MathNet.Numerics.LinearAlgebra
type RealMatrix2x2 =
| RealMatrix2x2 of Matrix<double>
static member private createInternal (a : #seq<#seq<double>>) =
matrix a |> RealMatrix2x2
static member create
(
(a11, a12),
(a21, a22)
) =
RealMatrix2x2.createInternal
[|
[| a11; a12|]
[| a21; a22|]
|]
let m2 =
(
(1., 2.),
(3., 4.)
)
|> RealMatrix2x2.create
The tuple signatures and "re-mapping" into #seq<#seq<double>> can be easily code-generated using, for example, Excel or any other convenient tool for as many dimensions as necessary. In fact, the whole class along with any other necessary operator overrides (like multiplication of RealMatrix2x2 by RealMatrix2x2, ...) can be code generated for all necessary dimensions.

F# function overloading with same parameter number

I have a simple F# function cost receiving a single parameter amount which is used for some calculations. It is a float so I need to pass in something like cost 33.0 which in math is the same as cost 33. The compiler complaints about it, and I understand why, but I would like being able to call it like that, I tried to create another function named the same and used type annotation for both of them and I also get compiler warnings. Is there a way to do this like C# does?
There are two mechanisms in F# to achieve this, and both do not rely on implicit casts "like C#":
(A) Method overloading
type Sample =
static member cost (amount: float) =
amount |> calculations
static member cost (amount: int) =
(amount |> float) |> calculations
Sample.cost 10 // compiles OK
Sample.cost 10. // compiles OK
(B) Using inlining
let inline cost amount =
amount + amount
cost 10 // compiles OK
cost 10. // compiles OK
F# doesn't allow overloading of let-bound functions, but you can overload methods on classes like in C#.
Sometimes, you can change the model to work on a Discriminated Union instead of a set of overloaded primitives, but I don't think it would be particularly sensible to do just to be able to distinguish between floats and integers.
if you want to use an int at call site but have a float inside the function body ; why not simply cast it ?
let cost amount =
// cast amount from to float (reusing the name amount to shadow the first one)
let amount = float amount
// rest of your function

How do I turn this Extension Method into an Extension Property?

I have an extension method
type System.Int32 with
member this.Thousand() = this * 1000
but it requires me to write like this
(5).Thousand()
I'd love to get rid of both parenthesis, starting with making it a property instead of a method (for learning sake) how do I make this a property?
Jon's answer is one way to do it, but for a read-only property there's also a more concise way to write it:
type System.Int32 with
member this.Thousand = this * 1000
Also, depending on your preferences, you may find it more pleasing to write 5 .Thousand (note the extra space) than (5).Thousand (but you won't be able to do just 5.Thousand, or even 5.ToString()).
I don't really know F# (shameful!) but based on this blog post, I'd expect:
type System.Int32 with
member this.Thousand
with get() = this * 1000
I suspect that won't free you from the first set of parentheses (otherwise F# may try to parse the whole thing as a literal), but it should help you with the second.
Personally I wouldn't use this sort of thing for a "production" extension, but it's useful for test code where you're working with a lot of values.
In particular, I've found it neat to have extension methods around dates, e.g. 19.June(1976) as a really simple, easy-to-read way of building up test data. But not for production code :)
It's not beautiful, but if you really want a function that will work for any numeric type, you can do this:
let inline thousand n =
let one = LanguagePrimitives.GenericOne
let thousand =
let rec loop n i =
if i < 1000 then loop (n + one) (i + 1)
else n
loop one 1
n * thousand
5.0 |> thousand
5 |> thousand
5I |> thousand

How do you print the resulting units using units of measure in F#?

I am beginning to learn how to use units of measure in F# but I haven't found the answer to this simple question yet. How do you print the resultant units after a calculation. I know that FSI prints them so they should be available somehow.
For example:
[<Measure>] type m;;
[<Measure>] type s;;
let d = 10<m>;;
val d : int<m> = 10
let t = 2<s>;;
val t : int<s> = 2
I want to do something like this:
printfn "Results: %A %A" (d / t) (UOM (d / t));;
"Results: 5 m/s"
Thanks in advance
Unfortunately, this is not possible.
Units of measure exist only at compile time. When you compile the program, they will be ereased (because .NET doesn't have any way of representing units for types). This means that at the runtime, the result of your calculation will be just float. I don't think there is any way other than just writing units as string in your code...
There was a related question some time ago. It has some more details and also explains why you cannot get information about units using reflection.
Why can not use reflection in f#

Resources