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#
Related
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.
I realize that you can express relationships with dimensions of units, like
[<Measure>] type cc = cm^3
and perform meaningful calculations later.
Given some unit of measure type,
[<Measure>] type m
Is it possible to define a unit in a relationship with a quantity of another unit? For example,
// doesn't compile
[<Measure>] type mm = 0.001<m>
// later
let length = 500.0<mm>
let length2 = 0.5<m>
printfn "%A" (length = length2) // prints true
In short: no.
Units of measure are annotations on primitives. Period. As you probably know, they will be deleted during compilation.
So here's their fundamental limitation: you cannot attach any kind of functionality to them, because they will all turn into plain old floats.
The compiler will check that your expressions are dimensionally valid, but (for now) it does not automatically generate or insert any sort of 'default' type-conversion functions.
You must write and use those functions yourself, and the best you can do is to make them as straightforward as possible.
Here's how I'd organise your example:
[<Measure>] type mm
[<Measure>] type mt
// first, I like to define basic functions to quickly annotate dimensionless values
let mm = (*) 1.0<mm>
let mt = (*) 1.0<mt>
// we define a constant conversion
let MmPerMt = 1000.0<mm/mt>
// (though nothing forbids us from defining any conversion we want, and the compiler cannot privilege one over another)
let INeverPaidAttentionInGradeSchool = 12345<mm/mt>
// for ease of use, we bake the conversion constant into functions
let MtToMm = (*) MmPerMt
// usage
let someUserInputInMeters = "12414.23"
let desiredValueInMillimeters = someUserInputInMeters
|> float
|> mt
|> MtToMm
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)
Probably a silly question, but I just got started with F# and I've got a little problem.
Say I have a function like this:
let multiplyByTwo x = x * 2
When I call this like this:
let result = multiplyByTwo 5
Everything is alright, the result is 10.
When I call it like this:
let result = multiplyByTwo 2.5
I expect to get 5 or 5.0 as a result. The actual result however is this:
let result = multiplyByTwo 2.5;;
---------------------------------^^^
stdin(4,28): error FS0001: This expression was expected to have type
int
but here has type
float
Because I want this function to be somewhat generic (i.e. accept both floating point numbers and integers), I don't like this. My question of course: how does one solve this?
When you write a numeric literal in F# (such as 2 or 3.14), the compiler treats that as a value of a specific type and so code that uses numeric literals will not be polymorphic. You can either convert input to a single type and work with that type (like float in desco's answer) or use more advanced features of F#...
Certain numeric operations can be written in a polymorphic way, if you mark the code as inline (this way, the compiler can represent additional constraints and statically resolve them) and if you only use polymorphic primitives (with additional static constraints).
Standard operators are polymorpic in inline functions and the F# library provides a way to get polymorphic value representing 1 and 0 (though not 2), but that's enough to write the function you wanted:
let inline twoTimes n =
let one = LanguagePrimitives.GenericOne
n * (one + one)
twoTimes 2
twoTimes 2.0
If you want to make this nicer, you can define a numeric literal (see Daniel's answer to earlier StackOverflow question) and then you can actually write just:
let inline twoTimes n = n * 2G
The special numeric literal 2G is translated to a call to a function of NumericLiteralG which sums specified number of generic 1 values using the technique I used above (so it won't be efficient for large numbers!) For more information, you see also my recent article on writing generic numeric code in F#.
let inline mulBy2 x = (float x) * 2.0
let a = mulBy2 3 // 6.0 : float
let b = mulBy2 2.5 // 5.0 : float
let c = mulBy2 "4" // 8.0 : float
If you aren't afraid using "little hacks", this might be useful:
// Copied from Core.LanguagePrimitives.IntrinsicFunctions.retype
[<NoDynamicInvocation>]
let inline retype (x:'a) : 'b = (# "" x : 'b #)
let inline multiplyByTwo (x:'a) = x * (retype 2:'a)
// use
let result1 = multiplyByTwo 5 // 10
let result2 = multiplyByTwo 2.5 // 5.0
This construct is not type safe since type checking is done in runtime. Also, quotations are relatively slow.
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#