» Publishers, Monetize your RSS feeds with FeedShow: More infos (Show/Hide Ads)
"Applications such as searching and visualization that request information from servers often have the potential to overload the server by sending too many requests before the handling of existing requests has been completed. A simple and effective solution to this problem is cancellation. This article examines a simple system of two communicating sequential processes that use cancellation to implement a server that accepts requests, returns responses and uses cancellation to tear down outstanding requests in order to avoid system overload..."
To read this article and more, subscribe to The F#.NET Journal today!
"The MailboxProcessor in the F# standard library uses unbounded queues that can grow to be arbitrarily long. Consequently, the queue in a consumer can grow without limit if its producers overwhelm it with data. This article examines an elegant solution to this problem in the form of a bounded queue with asynchronous enqueue and dequeue operations that cause both producers and consumers to cooperatively suspend themselves until capacity or data are available to satisfy their request. Furthermore, this simpler architecture neatly decouples the sequential processes from the concurrent queues they use to communicate..."
To read this article and more, subscribe to The F#.NET Journal today!
The F#.NET Journal just published an article about garbage collection:
"When performance is important in a garbage collected language such as F# it is useful to have some understanding of the costs of operations that the garbage collector performs. This article provides an introduction to garbage collection, an overview of the processes performed by generational garbage collectors for multithreaded programs and goes on to examine some F# programs that deliberately exhibit pathological behaviour and presents workarounds that alleviate or even eliminate the costs associated with garbage collection on .NET..."
To read this article and more, subscribe to The F#.NET Journal today!
"Purely functional data structures such as the Set and Map collections provided by the F# standard library have many advantages over traditional imperative collections, particularly clarity due to the absence of mutation, but their performance can be much worse. Benchmarks have shown the F# Set and Map running up to 40× slower than the imperative HashSet and Dictionary collections provided by .NET. This article describes the design and implementation of a hash trie implementation of a set that is up to 7× faster to construct and up to 4.5× faster to search than the F# set..."
To read this article and more, subscribe to The F#.NET Journal today!
cosine(x) = 1 - x²/2! + x⁴/4! - x⁶/6! + ...
float-specific version in F#:let cosine n x =
let rec loop i q t c =
if i=n then c else
loop (i + 1) (q + 10 + 8*i) (-t * x * x / float q) (c + t)
loop 0 2 1.0 0.0
cosine 1000000 0.1
inline in order to remove the performance overhead of this parameterization:let inline cosine zero one ofInt ( ~-. ) ( +. ) ( *. ) ( /. ) n x =
let rec loop i q t c =
if i=n then c else
loop (i + 1) (q + 10 + 8*i) (-.t *. x *. x /. ofInt q) (c +. t)
loop 0 2 one zerofloat like this, which is just as fast as before:cosine 0.0 1.0 float ( ~- ) (+) (*) (/) 1000000 0.1
float:cosine 0.0f 1.0f float32 ( ~- ) (+) (*) (/) 1000000 0.1f
cosine 0N 1N BigNum.FromInt (~-) (+) (*) (/) 10 (1N / 10N)
type Expr =
| Int of int
| Var of string
| Add of Expr * Expr
| Mul of Expr * Expr
| Pow of Expr * Expr
static member (~-) f = Mul(Int -1, f)
static member (+) (f, g) = Add(f, g)
static member (*) (f, g) = Mul(f, g)
static member (/) (f, g) = Mul(f, Pow(g, Int -1))
cosine (Int 0) (Int 1) Int (~-) (+) (*) (/) 3 (Var "x")
-x*x out of loop.Let's solve the same problem using the F# programming language instead. We begin by defining the problem using a union type to represent the countries and nested lists to represent the adjacencies:
type Country =
| Brazil | FrenchGuiana | Suriname | Guyana | Venezuala | Colombia
| Ecuador | Peru | Chile | Bolivia | Paraguay | Uruguay | Argentina
let countries =
[|Brazil; FrenchGuiana; Suriname; Guyana; Venezuala; Colombia;
Ecuador; Peru; Chile; Bolivia; Paraguay; Uruguay; Argentina|]
let edges =
[
Brazil, [ FrenchGuiana; Suriname; Guyana; Venezuala; Colombia;
Peru; Bolivia; Paraguay; Uruguay; Argentina ]]
FrenchGuiana, [ Brazil; Suriname ]
Suriname, [ Brazil; FrenchGuiana; Guyana ]
Guyana, [ Brazil; Suriname; Venezuala ]
Venezuala, [ Brazil; Guyana; Colombia ]
Colombia, [ Brazil; Venezuala; Peru; Ecuador ]
Ecuador, [ Colombia; Peru ]
Peru, [ Brazil; Colombia; Ecuador; Bolivia; Chile ]
Chile, [ Peru; Bolivia; Argentina ]
Bolivia, [ Chile; Peru; Brazil; Paraguay; Argentina ]
Paraguay, [ Bolivia; Brazil; Argentina ]
Argentina, [ Chile; Bolivia; Paraguay; Brazil; Uruguay ]
Uruguay, [ Brazil; Argentina ]
These are the vertices and edges of our graph.
The countries of South America are, of course, a planar graph so we know they can be assigned colors with no two adjacent countries having the same color using a total of no more than four different colors. Let us define the set of all four possible colors as follows:
let allColors = set[0..3]
The graph coloring problem may then be solved by adding our vertices and edges to an empty graph, generating a sequence of possible colorings at each step:
let solve (V, E) =
((Set.empty, seq[Map.empty]), V)
||> Seq.fold (fun (vertices, solutions) vertex ->
let neighbors =
[|for src, dsts in E do
if src = vertex then yield! Set.intersect vertices (set dsts) else
for dst in dsts do
if dst = vertex && Set.contains src vertices then
yield src|]
Set.add vertex vertices,
seq { for color in solutions do
for newColor in allColors do
if Seq.forall (fun u -> color.[u] <> newColor) neighbors then
yield Map.add vertex newColor color })
Eric's result may then be obtained by taking the first of the valid colorings and using it to enumerate the colors of each country in turn:
let answer =
let _, colors = solve (countries, edges)
let color = Seq.head colors
[ for country in countries -> color.[country] ]
Remarkably, we have solved the same problem in just 19 lines of F# code! One can only imagine how much simpler Microsoft's Roslyn compiler could have been had it been written in F#...
The parallel matrix-matrix multiply makes heavy use of async for parallel programming, where it is an anti-pattern. So it may be productively rewritten using Tasks as follows:
let randomMatrix =
let rnd = new System.Random()
Array2D.init 500 500 (fun _ _ -> rnd.NextDouble())
let matrixMultiply (a:float[,]) (b:float[,]) =
let rowsA, colsA = Array2D.length1 a, Array2D.length2 a
let rowsB, colsB = Array2D.length1 b, Array2D.length2 b
let result = Array2D.create rowsA colsB 0.0
System.Threading.Tasks.Parallel.For(0, rowsA, fun i ->
for j in 0 .. colsB - 1 do
let mutable x = 0.0
for k in 0 .. colsA - 1 do
x <- x + a.[i,k] * b.[k,j]
result.[i,j] <- x
) |> ignore
result
matrixMultiply randomMatrix randomMatrix
This is 60x faster than the original async-based solution. However, this is a poor choice of algorithm because it lacks locality. Better algorithms are tiled or cache oblivious.
Their prime number generator makes heavy use of enumerable sequences which can be productively rewritten using recursion and arrays instead, as follows:
(* A very naive prime number detector *)
let isPrime (n:int) =
let rec loop i = i*i > n || (n % i <> 0 && loop (i+1))
loop 2
(* Return primes between m and n using multiple threads *)
let primes m n =
Array.Parallel.init (n-m+1) (fun i -> m+i, isPrime (m+i))
|> Array.Parallel.choose (function n, true -> Some n | _ -> None)
(* Run a test *)
while true do
let timer = System.Diagnostics.Stopwatch.StartNew()
primes 1000000000 1000100000
|> ignore
printfn "%fs" timer.Elapsed.TotalSeconds
This is 13x faster than their original seq-based solution.
Functional programming has immutable data structures and no side effect which are inherently suitable for parallel programming.
I investigate how to exploit multicore computation in a functional language, and target production code for some numerical applications.
F# has Microsoft behind its back, and its parallel constructs such as PLINQ, TPL, Async Workflow have been well-documented and shown some potentials.
However, research about parallelism in Haskell is very active at the moment, and it posseses many nice features which haven't supported by F# yet:
par requires that the programmer understand operational properties of the language that are at best implementation-defined (and at worst undefined). This makes par difficult to use, and pitfalls abound — new users have a high failure rate..."My question is which language should I choose for functional parallelism?
- The A* algorithm for route finding.
- Computing the "sliding median" or "moving median average" by maintaining queues of values in the window less than or equal to and greater than or equal to the current median, respectively.
"Stanford University maintain a database of 3D models, perhaps the most famous of which is the Stanford Bunny. This is a 3D scan of a statue of a rabbit. The tesselated version contains 65,000 triangles and is stored as plain text in a PLY file. This article describes a program that embeds the mesh data as an embedded resource in a .NET assembly, parses it at run-time and visualizes the results in 3D using Windows Presentation Foundation..."
To read this article and more, subscribe to The F#.NET Journal today!
> type Point = { X: float; Y: float };;
type Point =
{X: float;
Y: float;}
List.sort:> [ { X = 2.0; Y = 3.0 }
{ X = 2.0; Y = 2.0 }
{ X = 1.0; Y = 3.0 } ]
|> List.sort;;
val it : Point list = [{X = 1.0;
Y = 3.0;}; {X = 2.0;
Y = 2.0;}; {X = 2.0;
Y = 3.0;}]
X and then by Y.compare function.IComparable and friends. If you want to use a custom ordering for a few operations then you can use higher-order functions like List.sortBy and List.sortWith. For example, List.sortBy (fun p -> p.Y, p.X) will sort by Y and then X because F# generates the lexicographic comparison over 2-tuples for you (!). let dot xs ys =
Seq.map2 (*) xs ys
|> Seq.sum
let convolve xs ys =
let rec loop vs xs ys zs =
match xs, ys with
| x::xs, ys -> loop (dot ys (x::zs) :: vs) xs ys (x::zs)
| [], _::(_::_ as ys) -> loop (dot ys zs :: vs) [] ys zs
| _ -> List.rev vs
loop [] xs ys []
convolve [2; 3; 1; 4] [4; 1; 2; 3]Eval extension member provided by the FSharp.PowerPack.Linq DLL as follows:#r "FSharp.PowerPack.Linq.dll"
open Linq.QuotationEvaluation
let f = <@2 + 3@>
f.Eval()
open the Linq.QuotationEvaluation namespace to make this extension member available.Compile extension member that returns a suspension but it does not appear to improve performance.; lets you write a lists of pairs by mingling both commas and semicolons like this:[1, 2; 3, 4]
string(Seq.sumBy bigint.Parse (data.Split[|'\n'|])).Substring(0, 10)The F#.NET Journal just published an article about metaprogramming:
"F# comes from the MetaLanguage or ML family of languages that were specifically designed for metaprogramming, a subject that includes writing interpreters, compilers and theorem provers as well as tools that manipulate programs such as refactoring plugins for Visual Studio. This article goes back to F#'s roots to create a tiny JIT compiler capable of transforming high-level expression-based functions down to raw x86 machine code for run-time execution. Remarkably, the resulting compiler is just 170 lines of F# code..."
To read this article and more, subscribe to The F#.NET Journal today!
Maybe there are 3,000,000 C# developers and only 30,000 F# developers in the world today.
Then they go on to explain that common sense dictates that we must restrict the company to using only C# because there is an abundance of C# developers.
Even if we ignore the relative productivity of F# and C# developers, there is something very wrong with this picture. How many people know C# and not F# and how many know F# and not C#? To a good approximation, the answers are roughly 3,000,000 and 0, respectively. This is vitally important because it means that an accurate Venn diagram would show the F# bubble inside the C# bubble, like this:
So we are really talking about the set of people who know C# and the set of people who know both C# and F#.
The observation that the number of people who know both languages is no bigger than the number of people who know only C# is uninteresting because it is a mathematical certainty (the circle inside the other cannot be larger by definition) and, therefore, this observation conveys no information.
This accurate picture gives us a lot more information. The developers who have also learned F# are pioneers pushing the adoption of a new technology.
How will this diagram evolve over time? The F# bubble will grow bigger and out of the C# bubble as F# adoption grows and people will begin to learn F# without having first used C#. According to IT Jobs Watch, the number of UK job adverts containing the keyword F# is doubling every year (51 in Q1 2010, 121 in Q1 2011 and 235 in Q1 2012). If the F# market does not saturate, F# will overtake C++ in 5 years and reach the level C# is at in 2018.
In fact, the diagram applies generally to less and more skilled workforces:
Common sense does not dictate that companies should restrict themselves to using less skilled workers because they are abundant. Both kinds of workforce can be valuable. Deskilling is a means of cost cutting and upskilling can help to scale up revenue.
"The ability to visualize trees is vitally important in many different applications. This article examines at a simple but effective algorithm for visualizing trees and uses WPF to draw the results..."
To read this article and more, subscribe to The F#.NET Journal today!
"One of the advantages of the Common-Language Runtime (CLR) is the ability to compile run-time generated code to CIL and have it JIT compiled to native code and evaluated. Regular expressions in .NET are perhaps the most obvious practical application where this capability can pay dividends. This article covers a tiny compiler written in F# that generates and compiles CIL code on-the-fly..."
To read this article and more, subscribe to The F#.NET Journal today!














