I would like to use FSharpChart but there is no basic Chart for what I would like to display : a correlation matrix.
I therefore wrote some functions to draw on a bitmap, along the way that Tomas Petricek does for charting a pie-chart.
Is there any easy way for me to use this to extend FSharpChart ?
let drawCorrelation (udls:seq<'T>) (mapcorrel:Map<('T*'T), float>) =
let mainForm = new Form(Width = 1250, Height = 1050, Text = "Correlation matrix")
let boxChart = new PictureBox(BackColor = Color.White, Dock = DockStyle.Fill,SizeMode = PictureBoxSizeMode.CenterImage)
let matrixbm = new Bitmap(1200, 1000)
let gr = Graphics.FromImage(matrixbm)
gr.Clear(Color.White)
draw2D gr (drawCorrelationInner mapcorrel) 1200 1000 udls mapcorrel (mapcorrel |> Seq.map (fun kv -> kv.Value ) |> Seq.average)
boxChart.Image <- matrixbm
mainForm.Controls.Add(boxChart)
mainForm.Show()
Related
Lets assume I have a record like:
type Page = { footersize: Size }
what is the correct syntax to change only the Height of the footersize:
{ page with footersize = ??? }
TIA
Edit#1: "Size" is the size of a FrameworkElement, i.e.,
Size is in the .Net world as Size(width,height) and is a structure, not record. As tried below,
this does NOT work:
{p with footersize = {p.footersize with Height = 96 * 0.5}}
Error: This expression was expected to have type 'Size' but here as type Page.
The most direct way is to copy-update the whole object:
let page' =
{ page with
FooterSize = Size(page.FooterSize.Width, 100.)
}
If you have some deeper nesting, it gets a bit harder.
type Page = { FooterSize: Size }
type Document = { Title: string; Page: Page }
let document = { Title = "Fun and Profit"; Page = { FooterSize= Size(10., 10.) } }
To update height, now you have to do:
let document' = { document with Page = { document.Page with FooterSize= Size(document.Page.FooterSize.Width, 100.) }}
And that goes off screen! There's a language suggestion for nested record assignment, which would allow you to do { document with Page.FooterSize.Height = 100. } , but that's still a little ways off.
Lenses
type Lens<'a,'b> = ('a -> 'b) * ('a -> 'b -> 'a)
Don't worry if this seems confusing! It will become much clearer in time.
Lenses are the functional equivalent to C#'s property set technology™ (basically page.FooterSize.Height = 100. in C#).
They're quite simple, just a pair of getter, setter functions.
let getFooterSize (p: Page) = p.FooterSize
let setFooterSize (p: Page) size = { p with FooterSize = size }
let getPage (d: Document) = d.Page
let setPage (d: Document) page = { d with Page = page }
let getWH (s: Size) = s.Width, s.Height
let setWH (s: Size) (w, h) = Size(w, h)
Of course, we can get values by simply using the compose right operator:
let (w, h) = (getPage >> getFooterSize >> getWH) document
But setting doesn't compose.
But with just three simple operators, we can have something very readable:
let get (getter, _) = getter
let set (_, setter) = setter
let (>=>) (get_ab, set_ab) (get_bc, set_bc) =
get_ab >> get_bc,
fun a c -> set_ab a (set_bc (get_ab a) c)
Since our lenses are just pair of getters and setters:
let pageL = getPage, setPage
let footerL = getFooterSize, setFooterSize
let sizeL = getWH, setWH
That's it. Those are our lenses. We can now compose these lenses with the fish operator (>=>) we had defined.
let (footer_w, footer_h) = get (pageL >=> footerL >=> sizeL) document
let document' = set (pageL >=> footerL >=> sizeL) document (footer_w, 100.)
Of course, you can write a lens in a much shorter form:
let pageL : Lens<Document, Page> =
(fun d -> d.Page), (fun d p -> { d with Page = p })
I am new to F# and functional programming in general. Given a scenario where you want to iterate over a sequence or list of strings, and map that to a new list of a different type, WITH an accumulator, what is the correct functional approach? I can achieve this in F# using mutable variables, but I am struggling to find the right function to use for this. It's similar to map I think, but there is the notion of state.
In other words, I want to transform a list of strings into a list of win forms radio buttons, but for each new button I want to add 20 to the previous y coordinate. Something like:
new RadioButton(Text=str,Location=new Point(20,y+20),Width=350)
You can use List.fold:
open System.Drawing
open System.Windows.Forms
let getButtons () =
let strings = ["a"; "b"; "c"]
let (_, pointsRev) = List.fold (fun (offset, l) s -> (offset+20, (new RadioButton(Text=s, Location = new Point(20, offset), Width = 350))::l)) (0, []) strings
pointsRev |> List.rev
The state is a pair containing the current offset and the current output list. The output list is built in reverse order so has to be reversed at the end.
You could also use Seq.map2:
let points = Seq.map2 (fun offset s -> new RadioButton(Text=s, Location = new Point(20, offset)) (Seq.initInfinite ((*)20)) strings |> List.ofSeq
You can access and change variable by reference alike
let x = ref 0
x := !x + 5
new Point(20,!x+20)
and you can use such variable inside closures.
Also you can use mapi : http://msdn.microsoft.com/en-us/library/ee353425.aspx
And add value to y based on i alike new Point(20,i*20+20)
Using List.fold is a great idea (see the accepted answer).
Being an F# beginner myself, I split the fold out into a separate function and renamed some variables so I could understand things more clearly. This seems to work:
let buttonNames = ["Button1Name"; "Button2Name"]
let createRadioButton (offset, radioButtons) name =
let newRadioButton = new RadioButton(Text=name, Location=new Point(20, offset), Width=350)
(offset + 20, newRadioButton::radioButtons)
let (_, buttonsReversed) = buttonNames |> List.fold createRadioButton (0, [])
let buttons = buttonsReversed |> List.rev
I want to override the onPaint method to make it draw the objects in two lists defined in the constructor, problem being I can't access the lists from the overrided onPaint method, I get the error saying the list or constructor is not defined when trying to use listOfSquares or listOfCircles. So basically, how do I access these lists from that override?
type MainForm = class
inherit Form
val mutable g : Graphics // mutable means its not read-only
val mutable position : Point // position of the rectangle
new () as form = {g=null;position = new Point(0,0)} then
// double buffering
form.SetStyle (ControlStyles.UserPaint, true);
form.SetStyle (ControlStyles.DoubleBuffer, true);
form.SetStyle (ControlStyles.AllPaintingInWmPaint, true);
form.Width <- 900
form.Height <- 500
form.BackColor <- Color.White
form.Text <- "2D Graphics Editor";
let listOfSquares = ResizeArray()
let listOfCircles = ResizeArray()
let menu = new MenuStrip()
let file = new ToolStripDropDownButton("File") // Menu
ignore(menu.Items.Add(file))
let create = new ToolStripDropDownButton("Create") // Menu
ignore(menu.Items.Add(create))
let square = create.DropDownItems.Add("Square")
let circle = create.DropDownItems.Add("Circle")
let newFile = file.DropDownItems.Add("New file")
let saveFile = file.DropDownItems.Add("Save file")
let openFile = file.DropDownItems.Add("Open file")
square.Click.Add(fun _ -> listOfSquares.Add(new square(5.0, 5.0)) |> ignore)
circle.Click.Add(fun _ -> listOfCircles.Add(new circle(10.0, 10.0)) |> ignore)
newFile.Click.Add(fun _ -> MessageBox.Show("newFile") |> ignore)
saveFile.Click.Add(fun _ -> MessageBox.Show("saveFile") |> ignore)
openFile.Click.Add(fun _ -> MessageBox.Show("openFile") |> ignore)
let dc c = (c :> Control)
form.Controls.AddRange([|dc menu|]);
// show the form
form.Show()
// override of paint event handler
override form.OnPaint e =
let g = e.Graphics in
// draw objects in listOfSquares and listOfCircles
end
If you did want to use a primary constructor then you could do it like this, using let bindings for all your private fields and do bindings for the constructor's code. The let bindings are accessible to all non-static members.
See the F# documentation on classes to read about this syntax.
type MainForm() as form =
inherit Form()
let mutable g : Graphics = null
let mutable position : Point = Point(0,0)
let listOfSquares = ResizeArray()
let listOfCircles = ResizeArray()
do
form.SetStyle (ControlStyles.UserPaint, true);
// ... your other initialization code
// show the form
form.Show()
override form.OnPaint e =
let g = e.Graphics
// draw objects in listOfSquares and listOfCircles
You defined their scope as being the constructor rather than the object. Move their declarations up to where position and g are defined.
I think this satisfies your requirements:
type test =
val mutable private temp:int
new() as this = {temp=5} then
this.temp <- 6
The important bits are the private access modifier, the assignment of the private field in the secondary constructor using the {..} syntax and the use of this to access private members.
Here is your code rewritten to properly initialize your lists:
type MainForm =
inherit Form
val mutable g : Graphics // mutable means its not read-only
val mutable position : Point // position of the rectangle
val listOfSquares : ResizeArray
val listOfCircles : ResizeArray
new () as form = {g=null;position = new Point(0,0)} then
// double buffering
form.SetStyle (ControlStyles.UserPaint, true);
form.SetStyle (ControlStyles.DoubleBuffer, true);
form.SetStyle (ControlStyles.AllPaintingInWmPaint, true);
form.Width <- 900
form.Height <- 500
form.BackColor <- Color.White
form.Text <- "2D Graphics Editor";
listOfSquares <- ResizeArray()
listOfCircles <- ResizeArray()
let menu = new MenuStrip()
let file = new ToolStripDropDownButton("File") // Menu
ignore(menu.Items.Add(file))
let create = new ToolStripDropDownButton("Create") // Menu
ignore(menu.Items.Add(create))
let square = create.DropDownItems.Add("Square")
let circle = create.DropDownItems.Add("Circle")
let newFile = file.DropDownItems.Add("New file")
let saveFile = file.DropDownItems.Add("Save file")
let openFile = file.DropDownItems.Add("Open file")
square.Click.Add(fun _ -> listOfSquares.Add(new square(5.0, 5.0)) |> ignore)
circle.Click.Add(fun _ -> listOfCircles.Add(new circle(10.0, 10.0)) |> ignore)
newFile.Click.Add(fun _ -> MessageBox.Show("newFile") |> ignore)
saveFile.Click.Add(fun _ -> MessageBox.Show("saveFile") |> ignore)
openFile.Click.Add(fun _ -> MessageBox.Show("openFile") |> ignore)
let dc c = (c :> Control)
form.Controls.AddRange([|dc menu|]);
// show the form
form.Show()
// override of paint event handler
override form.OnPaint e =
let g = e.Graphics in
// draw objects in listOfSquares and listOfCircles
end
As #leafgarland demonstrated, if you don't need to use a secondary constructor, then use the primary constructor for much cleaner syntax.
type test() =
let mutable temp = 6
...
override form.OnPaint e =
let g = e.Graphics
printfn "%i" temp
I'm doing a project called "2D Shape editor" in f#. I have done this project in c# before so I've got all the logics for how to connect two shapes. So I know that i will need a list to hold all theese shapes that I will be adding. But I simply can't get my addToList method to work.
My ShapeList:
let mutable ShapeList:List<RectangleZ> = [RectangleZ(100,100)]
My add methods:
let addToList (listan:List<RectangleZ>) (element:RectangleZ) = let ShapeList = ShapeList#[element] in ShapeList
//Method to add into the ShapeList
let addToList (listan:List<RectangleZ>) (element:RectangleZ) = element::ShapeList
//Other try on adding into shapeList
the button that should be adding rectangles to the ShapeList:
btn.Click.Add(fun _ -> new RectangleZ(500, 100) |> addToList ShapeList |>ignore |> saver)
//Button click method that should be adding the RectangleZ(500, 100) to my ShapeList
And ofcourse my rectangle:
type RectangleZ(x:int, y:int)=
let mutable thisx = x
let mutable thisy = y
let mutable thiswidth = 50
let mutable thisheight = 20
let brush = new SolidBrush(Color.Black)
member obj.x with get () = thisx and set x = thisx <- x
member obj.y with get () = thisy and set y = thisy <- y
member obj.width with get () = thiswidth and set width = thiswidth <- width
member obj.height with get () = thisheight and set height = thisheight <- height
member obj.thisColor = Color.FromArgb(167, 198, 253)
member obj.draw(paper:Graphics) = paper.FillRectangle(brush, thisx, thisy, 50, 20)
member obj.ShapeType = "Rectangle"
The element dosn't get added into the list for some reason in neither of my addToList functions. My Question is why?
List in F# are immutable. This means that when you add item to list like this:
let newlist = elem :: tail;;
old list (tail) doesn't changes, instead of that new list created. So, you need to return new list from your addToList function and than update mutable variable:
let addToList (listan:List<RectangleZ>) (element:RectangleZ) = element::listan
ShapeList <- addToList ShapeList newElement
In your code let ShapeList is local and doesn't affect global ShapeList variable.
let newList = oldList # [newElement]
You can use List.append with mutable lists, the below example worked fine with me:
let mutable season_averages = []
for i in 0 .. n_seasons do
season_averages <- [i] |> List.append season_averages
printfn "Seasons Average: %A" season_averages
I'm hopeful that someone could potentially post an example of using FParsec where the data is based on some sort of incoming live stream.
Some examples could be producing a result based on mouse gestures, generating an alert or notification based on a specific sequence of stock ticks.
If someone could post an example it would be greatly appreciated.
Thanks!
What you're looking for is the Reactive Parsers out of Rxx.
This isn't F# but rather a .NET library that let's you write code such as (following from your stock example):
var alerts = ticks.Parse(parser =>
from next in parser
let ups = next.Where(tick => tick.Change > 0)
let downs = next.Where(tick => tick.Change < 0)
let downAlert = from manyUps in ups.AtLeast(2).ToList()
from reversalDown in downs.NonGreedy()
where reversalDown.Change <= -11
select new StockAlert(manyUps, reversalDown)
let upAlert = from manyDowns in downs.AtLeast(2).ToList()
from reversalUp in ups.NonGreedy()
where reversalUp.Change >= 21
select new StockAlert(manyDowns, reversalUp)
select downAlert.Or(upAlert).Ambiguous(untilCount: 1));
Credit of course goes to Dave Sexton and James Miles who did the majority of this work.
For background reading, the parser extensions to Rxx came out of this discussion: http://qa.social.msdn.microsoft.com/Forums/eu/rx/thread/0f72e5c0-1476-4969-92da-633000346d0d
Here's a very simple example of how this could be used in F#:
open Rxx.Parsers.Reactive
open Rxx.Parsers.Reactive.Linq
// F# shortcuts to Rxx
let where f (a:IObservableParser<_,_>) = a.Where(fun b -> f b)
let toList (parser:IObservableParser<_,_>) = parser.ToList()
let (<&>) (a:IObservableParser<'a,'b>) (b:IObservableParser<'a,'b>) = a.And(b)
let create a =
{ new ObservableParser<_,_>() with
override x.Start = a(x.Next) } :> IObservableParser<_,_>
let parse (parser:IObservableParser<_,_>) (obs:IObservable<_>) = obs.Parse(parser)
// example of grammar
let grammar =
(fun (parser:IObservableParser<_,_>) ->
let next = parser.Next
let bigs = next |> where(fun i -> i > 25)
let smalls = next |> where(fun i -> i <= 25)
bigs <&> smalls |> toList )
|> create
// the test
let random = Random()
let values = Observable.Interval(TimeSpan.FromMilliseconds(500.0)).Select( fun _ -> random.Next(1,50)).Trace().TraceSubscriptions("subbing","subbed","disposing","disposed").Publish()
let sub = values |> parse grammar |> Observable.add(printfn "BIG THEN SMALL: %A")
let test = values.Connect()