Today I released a new bugfix release for “FAKE – F# Make”. We fixed some path and logging issues and as a new feature we introduced the @@ operator which allows to combine paths.
Tags: F#, F#, F-sharp MakeToday I released a new bugfix release for “FAKE – F# Make”. We fixed some path and logging issues and as a new feature we introduced the @@ operator which allows to combine paths.
Tags: F#, F#, F-sharp Make| Comments (1) |
Yesterday I showed how we can map some of the Rx operators to an API which looks more like the F# base classes. Today I wanted to use these mapped operators in a WPF-application written in F#.
F# gives us a nice way to use events as first class citizen (via IEvent) but these events implement their own version of IObservable<T> (in FSharp.Core.dll), which is unfortunately incompatible with the Rx version and therefore with the mapped API.
The solution I found is to wrap the F# IEvent with a Rx IObservable<T>:
/// Generates an observable from an IEvent
let fromEvent (event:IEvent<_,_>) =
Observable.Create<_>(fun x ->
event.Subscribe x.OnNext |> ignore
new System.Action(fun () -> ()))
Now we are able to use the WPF events as observables:
// Register ListBox Commands
listBox1.KeyDown
|> Observable.fromEvent
|> Observable.filter (fun args -> args.Key = Key.Delete)
|> Observable.subscribe deleteElement
I am interested if someone has a different and maybe better solution to this problem.
Updated: 21.12.2009 – Observable.Context is no longer supported by Rx ==> Removed
Tags: F#, Reactive Framework| Comments (0) |
The “Reactive Extensions for .NET (Rx)” comes with lot’s of operators for using IObservable<T>. This code mimics the signature of the default F# sequence combinators and allows to use observables like sequences. It is a similar approach like Matthews Podwysocki’s blog post about mapping the IParallelEnumerable.
I will update this post from time to time to include more of the operators.
module RxExtensions.Observable
open System.Linq
open System
open System.Threading
open System.Windows.Threading
type ‘a observable = IObservable<’a>
type ‘a observer = IObserver<’a>
/// converts a lambda in a System.Action
let asAction f = new System.Action(f)
/// System.Action whichs does nothing
let doNothing = asAction (fun () -> ())
/// Creates an observer
let createObserver next error completed =
{new System.IObserver<_> with
member this.OnCompleted() = completed()
member this.OnError(e) = error e
member this.OnNext(args) = next args}
/// Creates a new observable
let create f =
Observable.Create<_>(fun x ->
f x
doNothing)
/// Creates a observable from a async
let ofAsync async =
create
(fun obs ->
Async.StartWithContinuations
(async,obs.OnNext,obs.OnError,obs.OnError))
/// Gets a dispatcher Schdeuler for the current dispatcher
let getDispatcherScheduler _ =
new DispatcherScheduler(Dispatcher.CurrentDispatcher)
/// Generates an observable from an IEvent
let fromEvent (event:IEvent<_,_>) = create (fun x -> event.Add x.OnNext)
/// Generates an empty observable
let empty<’a> = Observable.Empty<’a>()
/// Takes the head of the elements
let head = Observable.First
/// Merges the two observables
let mergeWith obs1 obs2 = Observable.Merge(obs2, obs1)
/// Merges all observables
let mergeAll (observables:IObservable<IObservable<’a>>) =
Observable.Merge observables
/// Merges all observables
let merge (observables:(IObservable<’a>) seq) =
Observable.Merge observables
/// Creates a range as an observable
let range start count = Observable.Range(start, count)
/// Converts a seq in an observable
let toObservable (seq: ‘a seq) = Observable.ToObservable seq
/// Converts a observable in a seq
let toEnumerable = Observable.ToEnumerable
/// Subscribes to the Observable with all 3 callbacks
let subscribeComplete next error completed (observable: ‘a observable) =
observable.Subscribe(
(fun x -> next x),
(fun e -> error e),
(fun () -> completed()))
/// Subscribes to the Observable with a
/// next and an error-function
let subscribeWithError next error observable =
subscribeComplete next error (fun () -> ()) observable
/// Subscribes to the Observable with just a next-function
let subscribe next observable =
subscribeWithError next ignore observable
/// throttles the observable for the given interval
let throttle interval observable =
Observable.Throttle(observable,interval)
/// throttles the observable scheduled on the current dispatcher
let throttleOnCurrentDispatcher interval observable =
Observable.Throttle(
observable,getDispatcherScheduler(),interval)
/// samples the observable at the given interval
let sample interval observable =
Observable.Sample(observable,interval)
/// samples the observable at the given interval
/// scheduled on the current dispatcher
let sampleOnCurrentDispatcher interval observable =
Observable.Sample(
observable,getDispatcherScheduler(),interval)
/// returns the observable sequence that reacts first.
let takeFirstOf2Reactions obs1 obs2 =
Observable.Amb(obs1,obs2)
/// returns the observable sequence that reacts first.
let amb (obs: IObservable<’a> seq) =
Observable.Amb obs
/// returns the observable sequence that reacts first.
let takeFirstReaction (obs: IObservable<’a> seq) =
Observable.Amb obs
/// Matches when both observable sequences
/// have an available value.
let both obs1 obs2 = Observable.And(obs1,obs2)
/// Merges two observable sequences
/// into one observable sequence.
let zip obs1 obs2 =
Observable.Zip(obs1, obs2, Func<_,_,_>(fun a b -> a, b))
/// Merges two observable sequences into one observable sequence
/// whenever one of the observable sequences has a new value.
/// ==> More results than zip
let combineLatest obs1 obs2 =
Observable.CombineLatest(
obs1, obs2, Func<_,_,_>(fun a b -> a, b))
/// Concats the two observables to one observable
let concat observable =
Observable.SelectMany(
observable,
Func<_,_>(fun (x:IObservable<’a>) -> x))
/// maps the given observable with the given function
let map f observable =
Observable.Select(observable,Func<_,_>(f))
/// maps the given observable with the given function
let mapi f observable =
Observable.Select(observable,Func<_,_,_>(fun x i ->f i x))
/// Filters all elements where the given predicate is satified
let filter f observable =
Observable.Where(observable, Func<_,_>(f))
/// Splits the observable into two observables
/// Containing the elements for which the predicate returns
/// true and false respectively
let partition predicate observable =
filter predicate observable,
filter (predicate >> not) observable
/// Skips n elements
let skip n observable = Observable.Skip(observable, n)
/// Skips elements while the predicate is satisfied
let skipWhile f observable =
Observable.SkipWhile(observable, Func<_,_>(f))
/// Runs all observable sequences in parallel
/// and combines their first values.
let forkJoin (observables: (‘a observable) seq) =
Observable.ForkJoin observables
/// Counts the elements
let length = Observable.Count
/// Takes n elements
let take n observable =
Observable.Take(observable, n)
/// Determines whether the given observable is empty
let isEmpty observable = Observable.IsEmpty observable
/// Determines whether the given observable is not empty
let isNotEmpty observable = not (Observable.IsEmpty observable)
/// Determines whether an observable sequence
/// contains a specified value
/// which satisfies the given predicate
let exists predicate observable =
observable
|> skipWhile (predicate >> not)
|> isNotEmpty
/// Continues an observable sequence that is terminated
/// by an exception with the next observable sequence.
let catch (newObservable:IObservable<’a>) failingObservable =
Observable.Catch(failingObservable,newObservable)
/// Takes elements while the predicate is satisfied
let takeWhile f observable =
Observable.TakeWhile(observable, Func<_,_>(f))
/// Iterates through the observable
/// and performs the given side-effect
let perform f observable =
Observable.Do(observable,fun x -> f x)
/// Invokes finallyAction after source observable
/// sequence terminates normally or by an exception.
let performFinally f observable =
Observable.Finally(observable,fun _ -> f())
/// Folds the observable
let fold f seed observable =
Observable.Aggregate(observable, seed, Func<_,_,_>(f))
/// Retruns an observable from a async pattern
let fromAsync beginF endF =
Observable.FromAsyncPattern<_>(
Func<_,_,_>(fun x y -> beginF(x,y)),
(fun x -> endF x)).Invoke()
/// Runs all observable sequences in parallel
/// and combines their first values.
let subscribeAll next observables =
observables |> Seq.map (subscribe next) |> Seq.toList
type IObservable<’a> with
/// Subscribes to the Observable with just a next-function
member this.Subscribe(next) =
subscribe next this
/// Subscribes to the Observable with a next
/// and an error-function
member this.Subscribe(next,error) =
subscribeWithError next error this
/// Subscribes to the Observable with all 3 callbacks
member this.Subscribe(next,error,completed) =
subscribeComplete next error completed this
open System.Net
type WebRequest with
member this.GetRequestStreamAsync() =
fromAsync
this.BeginGetRequestStream
this.EndGetRequestStream
member this.GetResponseAsync() =
fromAsync
this.BeginGetResponse
this.EndGetResponse
member this.GetResponseStreamAsync() =
fromAsync
this.BeginGetRequestStream
this.EndGetRequestStream
type Async<’a> with
member this.ToObservable() = ofAsync this
| Comments (5) |
I just released a new version of my Open Source Build Automation Framework “FAKE – F# Make”. You can read more about FAKE on the project website or in the Getting started with "FAKE – F# Make"-article.
Although the new release contains many bugfixes, I only want to show the two major improvements here.
From now on FAKE uses the “F# Interactive” (fsi.exe) instead of the F# Compiler (fsc.exe) to run the build scripts, which brings two major improvements.
Due to the fact that FAKE scripts are no longer compiled at the beginning of the build process, we don’t need a temporary folder for the created binaries.
The #load command in F# scripts allows us to load modules at runtime. Now we are able to put reusable Targets or TargetTemplates (see below) into external build script files.
TargetTemplates provide an easy way to reuse common Targets. Let’s consider a (very) small sample:
Target "TraceHello" (fun () ->
trace "Hello World from FAKE"
)
This Target “TraceHello” traces a “Hello World” string into our build log. Now we want it to be slightly more generic and to trace a custom string. We can do this by using a TargetTemplate:
/// createTraceTarget: string -> string -> Target
let createTraceTarget = TargetTemplate (fun s ->
trace s
)
Now we have a template (or a function which generates targets) that gets a string for the target name and a string for the trace text and generates a usable target:
createTraceTarget "TraceHello" "Hello World from FAKE"
createTraceTarget "Trace2" "Trace another text"
Of course the TargetTemplate function is generic and can be used with any tuple as parameter:
/// createTraceTarget: string -> string*int -> Target
let createTraceTarget = TargetTemplate (fun (s,d) ->
trace s
trace <| sprintf "my int: %d" d
)
createTraceTarget "TraceHello" ("Hello World from FAKE",2)
createTraceTarget "Trace2" ("Trace another text",42)
| Comments (1) |
In this tutorial I will describe how you can set up a complete build infrastructure with “FAKE – F# Make”. You will learn:
“FAKE – F# Make” is completely written in F# and all build scripts will also be written in F#, but this doesn’t imply you have to learn programming in F#. In fact the “FAKE – F# Make” syntax is very easy to learn. But if you need to you can use the complete power of F# and the .NET Framework.
But in order to get things working we need to install the F# environment. You can download the F# April 2010 CTP from the Microsoft F# Developer Center or install Visual Studio 2010.
Now download the latest CalculatorSample-*.zip from the FAKE Download site. This sample includes 3 tiny projects and basically the following structure:
Open the file tools\FAKE\FakeLib.dll.config and check if the default configuration matches your system environment:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="MSBuildPath"
value="c:\Windows\Microsoft.NET\Framework\v4.0.30319\" />
<add key="FSIPath"
value="[ProgramFiles]\FSharp-2.0.0.0\bin\" />
</appSettings>
</configuration>
If you run the build.bat from the command line then your first FAKE script (build.fsx) will be executed. If everything works fine you will get the following output:

Now open the build.fsx with Visual Studio. It should look like this:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Default target
Target? Default <-
fun _ –> trace "Hello World from FAKE"
// start build
Run? Default
As you can see the code is really simple. The very first lines include the FAKE libraries and are vital in all FAKE build scripts.
After this header the Default target is defined. A target definition contains of two important parts. The first is the name of the target (here “Default”) and the second is an action (here a simple trace of “Hello world”). Action can be defined as lambda expressions or methods.
The last line runs the “Default” target – which means it executes the defined action.
A typical first step in nearly every build scenario is to clean the output of the last build. We can achieve this by modifying the build.fsx to the following:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
// Targets
Target? Clean <-
fun _ -> CleanDir buildDir
Target? Default <-
fun _ -> trace "Hello World from FAKE"
// Dependencies
For? Default <- Dependency? Clean
// start build
Run? Default
We introduced some new concepts in this snippet. At first we defined a global property called “buildDir” with the relative path of a temporary build folder.
In the Clean target we want the CleanDir task to clean up this build directory. This simply deletes all files in the folder or creates the directory if necessary.
In the dependencies section we say that the Default target is dependent of the Clean target. In other words Clean is a prerequisite of Default and will be run before the execution of Default:
In the next step we want to compile our application libraries, which means we want to compile all projects under /src/app with MSBuild.
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
let appReferences = Scan (!+ @"src\app\**\*.csproj")
// Targets
Target? Clean <-
fun _ -> CleanDir buildDir
Target? BuildApp <-
fun _ ->
let target = "Build"
// compile all projects below src/app/ in Release mode
let apps = MSBuildRelease buildDir target appReferences
// log the output files
Log "AppBuild-Output: " apps
Target? Default <-
fun _ -> trace "Hello World from FAKE"
// Dependencies
For? BuildApp <- Dependency? Clean
For? Default <- Dependency? BuildApp
// start build
Run? Default
Again, we defined a new build target named “BuildApp” which compiles all project files given in the property appReferences with the MSBuild task. The output will be copied to buildDir.
In order to find the right project files “FAKE – F# Make” scans the folder src/app/ and all subfolders with the given pattern. Therefore a similar FileSet definition like in NAnt or MSBuild (see project page for details) is used.
In addition the target dependencies are modified. Now Default is dependent of BuildApp and BuildApp needs Clean as a prerequisite.
This means the execution order is: Clean ==> BuildApp ==> Default.
Now our main application will be built automatically and it’s time to build the test application. We use pretty the same concepts as before:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
let testDir = @".\test\"
let appReferences = !+ @"src\app\**\*.csproj" |> Scan
let testReferences = !+ @"src\test\**\*.csproj" |> Scan
// Targets
Target? Clean <-
fun _ –>
CleanDir buildDir
CleanDir testDir
Target? BuildApp <-
fun _ ->
let target = "Build"
// compile all projects below src/app/ in Release mode
let apps = MSBuildRelease buildDir target appReferences
// log the output files
Log "AppBuild-Output: " apps
Target? BuildTest <-
fun _ ->
let testApps = MSBuildDebug testDir "Build" testReferences
Log "TestBuild-Output: " testApps
Target? Default <-
fun _ -> trace "Hello World from FAKE"
// Dependencies
For? BuildApp <- Dependency? Clean
For? BuildTest <- Dependency? Clean
For? Default <-
Dependency? BuildApp
|> And? BuildTest
// start build
Run? Default
This time we define a new target “BuildTest”, which compiles all C# projects below src/test/ in Debug mode and we mark the target as a dependency of Default.
As you can see the Clean target is now a dependency of BuildApp and BuildTest, since we also have to clean the test dir. Although the Clean target is referenced twice the “FAKE – F# Make” runtime ensures that it will only be executed once.
The execution order is now Clean ==> BuildApp ==> BuildTest ==> Default.
Now all our projects will be compiled and we can use the NUnit task in order to test our test assemblies:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
let testDir = @".\test\"
let appReferences = !+ @"src\app\**\*.csproj" |> Scan
let testReferences = !+ @"src\test\**\*.csproj" |> Scan
let testAssemblies = !+ (testDir + @"\NUnit.Test.*.dll") |> Scan
let nunitPath = @".\Tools\NUnit\bin"
let nunitOutput = testDir + @"TestResults.xml"
// Targets
Target? Clean <-
fun _ ->
CleanDir buildDir
CleanDir testDir
Target? BuildApp <-
fun _ ->
let target = "Build"
// compile all projects below src/app/ in Release mode
let apps = MSBuildRelease buildDir target appReferences
// log the output files
Log "AppBuild-Output: " apps
Target? BuildTest <-
fun _ ->
let testApps = MSBuildDebug testDir "Build" testReferences
Log "TestBuild-Output: " testApps
Target? Test <-
fun _ ->
NUnit (fun p ->
{p with
ToolPath = nunitPath;
DisableShadowCopy = true;
OutputFile = nunitOutput})
testAssemblies
Target? Default <-
fun _ -> trace "Hello World from FAKE"
// Dependencies
For? BuildApp <- Dependency? Clean
For? BuildTest <- Dependency? Clean
For? Test <-
Dependency? BuildApp
|> And? BuildTest
For? Default <- Dependency? Test
// start build
Run? Default
Our new target “Test” scans the test directory for test assemblies and runs them with NUnit. The mysterious part (fun p –> …) simply overrides the default parameters of the NUnit task and allows to specify concrete parameters.
The execution order is now Clean ==> BuildApp ==> BuildTest ==> Test ==> Default.
Now we want to deploy a *.zip file containing our application:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
let testDir = @".\test\"
let deployDir = @".\deploy\"
let appReferences = !+ @"src\app\**\*.csproj" |> Scan
let testReferences = !+ @"src\test\**\*.csproj" |> Scan
let testAssemblies = !+ (testDir + @"\NUnit.Test.*.dll") |> Scan
let nunitPath = @".\Tools\NUnit\bin"
let nunitOutput = testDir + @"TestResults.xml"
let filesToZip = !+ (buildDir + "\**\*.*") — "*.zip" |> Scan
let zipFileName = deployDir + "Calculator.zip"
// Targets
Target? Clean <-
fun _ -> CleanDirs [buildDir; testDir; deployDir]
Target? BuildApp <-
fun _ ->
let target = "Build"
// compile all projects below src/app/ in Release mode
let apps = MSBuildRelease buildDir target appReferences
// log the output files
Log "AppBuild-Output: " apps
Target? BuildTest <-
fun _ ->
let testApps = MSBuildDebug testDir "Build" testReferences
Log "TestBuild-Output: " testApps
Target? Test <-
fun _ ->
NUnit (fun p ->
{p with
ToolPath = nunitPath;
DisableShadowCopy = true;
OutputFile = nunitOutput})
testAssemblies
Target? Deploy <-
fun _ -> Zip buildDir zipFileName filesToZip
Target? Default <- DoNothing
// Dependencies
For? BuildApp <- Dependency? Clean
For? BuildTest <- Dependency? Clean
For? Test <-
Dependency? BuildApp
|> And? BuildTest
For? Deploy <- Dependency? Test
For? Default <- Dependency? Deploy
// start build
Run? Default
The new target “Deploy” scans the build directory for all files but zip-files. The result will be zipped to \deploy\Calculator.zip via the Zip task.
The execution order is now Clean ==> BuildApp ==> BuildTest ==> Test ==> Deploy ==> Default whereas Default now is only used as a entry point.
Now your build file should look like completeBuild.fsx and you are ready to write your own “FAKE – F# Make” build scripts. If you have any questions or suggestions feel free to comment on this post.
In the next article I will show how we can add FxCop to our build in order to check specific naming rules.
Tags: F#, F-sharp Make, Fake, MSBuild, NAnt, Rake| Comments (3) |
If your wondering how Google computes query results in such a short time you have to read the famous “MapReduce”-Paper by Jeffrey Dean and Sanjay Ghemawat (2004). It shows how one can split large tasks into a mapping and a reduce step which could then be processed in parallel.
With PLINQ (part of the Parallel Extensions to the .NET Framework) you can easily use “MapReduce”-pattern in .NET and especially F#. PLINQ will take care of all the MultiThreading and load balancing stuff. You only have to give PLINQ a map and a reduce (or fold) function.
Lets consider a small example. Someone wants to compute the sum of the factorials of all integers from 1 to 3000. With List.map and List.fold_left this is a very easy task in F#:
#light
open System
let add a b = a + b
let fac (x:bigint) = [1I..x] |> List.fold_left (*) 1I
let sum =
[1I..3000I]
|> List.map fac
|> List.fold_left add 0I
printfn "Sum of Factorials: %A" sum
Of course you could do much much better if you don’t compute every factorial on its own (I will show this in one of the next parts) – but for this time I need an easy function that is time consuming.
This simple Task needs 27 sec. on my Core 2 Duo E6550 with 2.33 GHz and 3.5 GB RAM.
But we can do better if we use parallel map and fold functions with help of PLINQ:
let pMap (mapF:'a -> 'b) (data:IParallelEnumerable<'a>) =
ParallelEnumerable.Select(data, mapF)
let pFold foldF seed (data:IParallelEnumerable<'a>)=
ParallelEnumerable.Aggregate<'a,'b>(
data, seed, new Func<'b,'a,'b>(foldF))
Now we can easily transform our calculation to a parallel version:
let sum =
[1I..3000I].AsParallel<bigint>()
|> pMap fac
|> pFold add 0I
Putting all together we can write a small test application:
#light
open System
open System.Linq
open System.Diagnostics
let testRuntime f =
let watch = new Stopwatch()
watch.Start()
(f(),watch.Elapsed)
let add a b = a + b
let fac (x:bigint) = [1I..x] |> List.fold_left (*) 1I
let list = [1I..3000I]
let pMap (mapF:'a -> 'b) (data:IParallelEnumerable<'a>)=
ParallelEnumerable.Select(data, mapF)
let pFold foldF seed (data:IParallelEnumerable<'a>)=
ParallelEnumerable.Aggregate<'a,'b>(
data, seed, new Func<'b,'a,'b>(foldF))
let PLINQ() =
list.AsParallel<bigint>()
|> pMap fac
|> pFold add 0I
let sequential() =
list
|> List.map fac
|> List.fold_left add 0I
let (sumSequential,timeSequential) =
testRuntime sequential
printfn "Time Normal: %.3fs" timeSequential.TotalSeconds
let (sumPLINQ,timePLINQ) =
testRuntime PLINQ
printfn "Time PLINQ: %.3fs" timePLINQ.TotalSeconds
timePLINQ.TotalSeconds / timeSequential.TotalSeconds
|> printfn "Ratio: %.2f"
sumSequential = sumPLINQ
|> printfn "Same Results: %A"
On my machine I get the following results:
Time Normal: 27.955s
Time PLINQ: 15.505s
Ratio: 0.55
Same Results: true
This means I get nearly a perfect load balancing on my two processors for this task.
In part II I describe how one can compute a series of functions in parallel.
Tags: F#, F#, Google, Map and fold, MapReduce, Parallel Computing, Parallel Extensions, PLINQ| Comments (0) |