I have a question concerning WebSharper's Google Visualization library. I was trying to format the data when the mouse hovers over countries in a Geo Chart.
However, there is the following definition for Legend on https://github.com/intellifactory/websharper.google.visualization/blob/master/IntelliFactory.WebSharper.Google.Visualization/Base.fs
type Legend [<Inline "{}">] () =
[<DefaultValue>]
val mutable position : LegendPosition
[<DefaultValue>]
val mutable alignment : LegendAlignment
[<DefaultValue>]
val mutable textStyle : TextStyle
This does not take into account the numberFormat which is used in such charts as GeoChart
https://developers.google.com/chart/interactive/docs/gallery/geochart
Is there a way to circumvent this (to format tooltips/legends) ?
Many thanks
A general workaround: the x?y <- z dynamic assignment can be used in WebSharper code to get x.y = z in the JavaScript translation. So in your case, for example legend?numberFormat <- ".##".
You can also expand the legend type with a helper method for this:
type Legend with
[<JavaScript; Inline>]
member this.WithNumberFormat(format: string) =
this?numberFormat <- format
this
Or you can create a JavaScript object expression by New [ "numberformat" => ".##" ] to use as the Legend object.
WebSharper's Google.Visualization typed bindings are a bit outdated. We will get around to review it completely someday, but feel free to create a pull request if you encounter any missing API functionality.
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 understand that in order to pretty print things like discriminated unions in Deedle, you have to override ToString(). But what about built in types, like float?
Specifically, I want floats in one column to be displayed as percentages, or at the very least, to not have a million digits past the decimal.
Is there a way to do this?
There is no built-in support for doing this - it sounds like a useful addition, so if you want to contribute this to Deedle, please open an issue to discuss this! We'd be happy to accepta pull request that adds this feature.
As a workaround, I think your best chance is to transform the data in the frame before printing. Something like this should do the trick:
let df = frame [ "A" => series [ 1 => 0.001 ] ]
df |> Frame.map (fun r c (v:float) ->
if c = "A" then box (sprintf "%f%%" (v*100.0)) else box v)
This creates a new frame where all float values of a column named A are transformed using the formatting function sprintf "%f%%" (v*100.0) and the rest is left unchanged.
I'm working through the charting and comparing prices tutorial on tryfsharp.org and my Chart.Combine function in Fsharp.Charting library will not work, but, other charts, such as Chart.Line will work! Code below.
// Helper function returns dates & closing prices from 2012
let recentPrices symbol =
let data = stockData symbol (DateTime(2012,1,1)) DateTime.Now
[ for row in data.Data -> row.Date.DayOfYear, row.Close ]
Chart.Line(recentPrices "AAPL", Name="Apple") //These two guys work when I try to plot them.
Chart.Line(recentPrices "MSFT", Name="Microsoft")
Chart.Combine( // This guy will not plot. Syntax found here: http://fsharp.github.io/FSharp.Charting/PointAndLineCharts.html
[ Chart.Line(recentPrices "AAPL", Name="Apple")
Chart.Line(recentPrices "MSFT", Name="Microsoft")])
I'd suggest you substituting your data generator function with something simpler and achieving correct plotting with this mockup first. For example, the following script:
#load #"<your path here>\Fsharp.Charting.fsx"
open System
open FSharp.Charting
let rand = System.Random
let recentPricesMock symbol =
[for i in 1..12 -> DateTime(2012,i,1),rand.Next(100)]
Chart.Combine (
[ Chart.Line(recentPricesMock "AAPL", Name="Apple")
Chart.Line(recentPricesMock "MSFT", Name="Microsoft")])
must plot combined mockup chart without any problems, as it does on my local box. From here you may drill down for the cause of original problem comparing your recentPrices with recentPricesMock.
EDIT: after getting to the full problematic source code I can point out two problems there that, as I was expecting, are in your choice of data rather, than in charting per se:
First, your definition of recentPrices converts dates into sequential day of year (row.Date.DayOfYear), so transition from 2012 into 2013 messes up your data and, consequently, charts. If you want to preserve your current functionality then it makes sense to redefine recentPrices as below
let recentPrices symbol =
let data = stockData symbol (DateTime(2012,1,1)) DateTime.Now
[ for row in data.Data -> row.Date, row.Close ]
Second, you chose a pair of stocks that doesn't scale well being combined on the single chart (AAPL in high hundreds $$, while MSFT in low tens $$), which adds to repetition of data points from first problem. After changing in your code AAPL to YHOO in addition to the recentPrices definition change described above
Chart.Combine ([
Chart.Line(recentPrices "YHOO", Name="Yahoo")
Chart.Line(recentPrices "MSFT", Name="Microsoft")
])
yields a beautiful smooth chart combo:
I thought that I might be able to do this with quotations - but I can't see how.
Should I just use a table of the functions with their names - or is their a way of doing this?
Thanks.
For more info......
I'm calling a lot of f# functions from excel and I wondered if I could write a f# function
let fs_wrapper (f_name:string) (f_params:list double) =
this bit calls fname with f_params
and then use
=fs_wrapper("my_func", 3.14, 2.71)
in the sheet rather than wrap all the functions separately.
You'll need to use standard .NET Reflection to do this. Quotations aren't going to help, because they represent function calls using standard .NET MethodInfo, so you'll need to use reflection anyway. The only benefit of quotations (compared to naive reflection) is that you can compile them, which could give you better performance (but the compilation isn't perfect).
Depending on your specific scenario (e.g. where are the functions located), you'd have to do something like:
module Functions =
let sin x = sin(x)
let sqrt y = sqrt(y)
open System.Reflection
let moduleInfo =
Assembly.GetExecutingAssembly().GetTypes()
|> Seq.find (fun t -> t.Name = "Functions")
let name = "sin"
moduleInfo.GetMethod(name).Invoke(null, [| box 3.1415 |])
Unless you need some extensibility or have a large number of functions, using a dictionary containing string as a key and function value as the value may be an easier option:
let funcs =
dict [ "sin", Functions.sin;
"sqrt", Functions.sqrt ]
funcs.[name](3.1415)
There are many methods but one way is to use Reflection, for instance:
typeof<int>.GetMethod("ToString", System.Type.EmptyTypes).Invoke(1, null)
typeof<int>.GetMethod("Parse", [|typeof<string>|]).Invoke(null, [|"112"|])
GetMethod optionally takes an array of types that define the signature, but you can skip that if your method is unambiguous.
Following up on what Thomas alluded to, have a look at Using and Abusing the F# Dynamic Lookup Operator by Matthew Podwysocki. It offers a syntactically clean way for doing dynamic lookup in F#.
How do F# immutable types interface with C#. I'm just starting to learn F# and I'd like to mix it in with some C# code I have, but I want my F# classes to be immutable.
Let's say we're making a Vector class in F#. Vector.X and Vector.Y should be re-assignable, but only be returning a new Vector class. In C# this would take allot of legwork to make .WithX(float x) clone the existing object and return a new one. Is there an easy way to do this in F#?
I've been searching for some time and I can't seem to find any docs on this. So any help would be great.
And finally, if I imported this class into C# what would its interface look like? Will the F# code restrict me from doing something stupid like Vector.X = 10?
This will look similar regardless of whether it's C# or F#.
You say "in C# it will take legwork", but cmon, I think
Vector WithX(float x) { return new Vector(x, this.Y); }
is it, right?
In both C# and F#, to prevent assignment to the X property, you author a property with a 'getter' but no 'setter'.
I think you're making all of this out to be harder than it is, or maybe I'm misunderstanding what you're asking.
EDIT
For the (I think rare) case of where there are 20 field and you may want to change just a small arbitrary subset of them, I found a cute hack to use F# and C# optional parameters together nicely.
F# Code:
namespace global
open System.Runtime.InteropServices
type Util =
static member Some<'T>(x:'T) = Some x
type MyClass(x:int, y:int, z:string) =
new (toClone:MyClass,
[<Optional>] ?x,
[<Optional>] ?y,
[<Optional>] ?z) =
MyClass(defaultArg x toClone.X,
defaultArg y toClone.Y,
defaultArg z toClone.Z)
member this.X = x
member this.Y = y
member this.Z = z
F# client code:
let a = new MyClass(3,4,"five")
let b = new MyClass(a, y=44) // clone a but change y
C# client code:
var m = new MyClass(3, 4, "five");
var m2 = new MyClass(m, y:Util.Some(44)); // clone m but change y
That is, optional parameters are a nice way to do this, and while C# optional parameters have some limitations, you can expose F# optional parameters in a way that works ok with C#, as suggested above.
F# Record types have a built in way of doing exactly what you're asking:
type Vector = {X:float; Y:float}
let v1 = {X=1.; Y=2.}
let v2 = {v1 with X=3.}
How that interops with C#, I'm not sure (edit: see Brian's comment).
Vector will be immutable from any .NET language, since X and Y are implemented as getters without setters.