Phillip Trelford's blog... evidently
when your only tool is an analogy, everything looks like a simile.

Exposing F# Dynamic Lookup to C#, WPF & Silverlight

May 23, 2010 15:20 by phil

Like C#, F# is primarily a statically typed programming language. That said both languages provide support for dynamic typing.

Sometimes dynamic typing can be a pragmatic way of solving a specific problem. For example say you’re a solutions provider with a core product and have a number of clients with bespoke requirements. One client asks for a product rating feature. This can be relatively easily achieved using dynamic properties:

  • a bunch of client specific properties are read from the database, including the rating value, which is then set as a dynamic property on the product object
  • zero changes are required to the core code
  • at the UI, on WPF, the dynamic property can simply be bound through XAML like any other object property
  • on Silverlight 4,0 direct binding is not currently possible, however there is a simple workaround - specifying the dynamic property as a parameter for a value converter (example later)

C# and F# use slightly different approaches for dynamic properties:

  • C# 4.0 provides a dynamic type, which tells the compiler that member lookup on the object should be deferred to run time
  • F# employs a dynamic lookup operator, which when overloaded defines the behaviour at runtime. This means that in F# dynamic lookup is explicit (the ? operator), and can be mixed with static lookup on the same object (the . operator)

Is it is still possible to implement dynamic properties in F# that can be consumed by other .Net languages like C#, VB.Net, IronRuby or IronPython; plus WPF and Silverlight. The trick is to inherit from .Net 4.0’s System.Dynamic.DynamicObject type and implement the System.ComponentModel.INotifyPropertyChanged interface:

open System.Dynamic

/// Dynamic Lookup type
type DynamicLookup () =
    inherit DynamicObject ()
    /// Synchronization object
    let sync = obj()
    /// Property Changed event
    let propertyChanged = Event<_,_>()    
    /// Properties
    let mutable properties = Map.empty
    /// Gets property value
    member private this.GetValue name = 
        Map.tryFind name properties
    /// Sets property value, creating a new property if none exists
    member private this.SetValue (name,value) =
        /// Atomically writes new properties reference
        let Write () = 
            properties <-
                properties 
                |> Map.remove name 
                |> Map.add name value
        // Synchronize property writes
        lock sync Write
        // Trigger property changed event
        (this,System.ComponentModel.PropertyChangedEventArgs(name))
        |> propertyChanged.Trigger    
    override this.TryGetMember(binder:GetMemberBinder,result:obj byref ) =     
        match this.GetValue binder.Name with
        | Some value -> result <- value; true
        | None -> false
    override this.TrySetMember(binder:SetMemberBinder, value:obj) =        
        this.SetValue(binder.Name,value)
        true
    override this.GetDynamicMemberNames() =
        properties |> Seq.map (fun pair -> pair.Key)
    [<CLIEvent>]
    member this.PropertyChanged = propertyChanged.Publish
    interface System.ComponentModel.INotifyPropertyChanged with
        [<CLIEvent>]
        member this.PropertyChanged = propertyChanged.Publish     
    static member (?) (lookup:#DynamicLookup,name:string) =
        match lookup.GetValue name with
        | Some(value) -> value
        | None -> raise (new System.MemberAccessException())        
    static member (?<-) (lookup:#DynamicLookup,name:string,value:'v) =
        lookup.SetValue (name,value)
    static member GetValue (lookup:DynamicLookup,name) =
        lookup.GetValue(name).Value

F# usage:

/// Product type inherits dynamic lookup
type Product (name,price) =
    inherit DynamicLookup ()
    member this.Name = name
    member this.Price = price
 
// Initiate product object with dynamic rating value
let p = Product("F# for Scientists",49.95M)
do p?Stars <- 5
// Access product's properties
let stars = System.Convert.ToInt32(p?Stars)
do printf "%s...%M %s" p.Name p.Price (System.String('*',stars))

C# usage:

// Create Product type with dynamic stars value
Product product = new Product("Expert F#",54.99M);
((dynamic)product).Stars = 5;       
// Read product properties
dynamic p = product;
string s = 
    string.Format("{0}...{1} {2}",
        p.Name, p.Price, new String('*', (int) p.Stars));

Use from Silverlight 4.0

<t:PropertyLookup x:Key="DynamicConverter"/>

 

<TextBox Text="{Binding Converter={StaticResource DynamicConverter},
                ConverterParameter=Stars}"/>

 

dynamic product = new Product("Real World FP", 35.99);
product.Stars = 5;
DataContext = product;

 

public class PropertyLookup : IValueConverter
{
    public object Convert(
        object value, 
        Type targetType, 
        object parameter, 
        CultureInfo culture)
    {        
        return DynamicLookup.GetValue(
            (DynamicLookup) value,
            (string) parameter);            
    }

    public object ConvertBack(object value, 
        Type targetType, 
        object parameter, 
        CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Note: Silverlight 4.0 requires Microsoft.CSharp.dll to use dynamic types.


Tags:
Categories: F# | WPF | Silverlight | Architecture | .Net | C#
Actions: E-mail | Permalink | Comments (4) | Comment RSSRSS comment feed

F# operator overloads for WPF dependency properties

May 17, 2010 00:15 by Phil

When creating a desktop application with WPF using F# there are a number of options:

For small desktop applications, the last option, creating WPF elements directly from F# can produce good self-contained code, but at time is a little less readable than the XAML equivalent. Lets consider placing a button bound to a command on a grid at a certain position.

The XAML fragment might look like this:

<Button Content="_1" Command="{Binding Key1Command}"
        Grid.Column="0" Grid.Row="2"/>

 

Code equivalent:

let button = Button(Content="_1")
button.SetBinding(Button.CommandProperty,Binding("Key1Command")) |> ignore
Grid.SetColumn(button,0)
Grid.SetRow(button,2)

 

Code equivalent using (+) operator overloads to add the dependency properties:

Button(Content="_1") + Button.Command(Binding "Key1Command") 
    + Grid.Column 0 + Grid.Row 2 

 

The glue is just a couple of classes that define a dependency property and value/binding pair with a (+) operator overload that sets the value on the target WPF element.

For Dependency Property values:

type DependencyPropertyValuePair(dp:DependencyProperty,value:obj) =
    member this.Property = dp
    member this.Value = value
    static member (+) 
        (target:#UIElement,pair:DependencyPropertyValuePair) =
        target.SetValue(pair.Property,pair.Value)
        target

 

For Dependency Property bindings:

type DependencyPropertyBindingPair(dp:DependencyProperty,binding:BindingBase) =
    member this.Property = dp
    member this.Binding = binding
    static member (+) 
        (target:#FrameworkElement,pair:DependencyPropertyBindingPair) =
        target.SetBinding(pair.Property,pair.Binding) |> ignore
        target

 

Finally relevant WPF types must be extended with helper methods (note: this could be code generated):

type Grid with
    static member Column (value:int) =
        DependencyPropertyValuePair(Grid.ColumnProperty,value)
    static member Row (value:int) =
        DependencyPropertyValuePair(Grid.RowProperty,value)

 

Attached is a sample calculator VS2010 project showing the mechanism in action.

Calculator

Calculator.zip (3.57 kb)


Tags:
Categories: F# | WPF
Actions: E-mail | Permalink | Comments (4) | Comment RSSRSS comment feed

Trading on IM with F#

May 6, 2010 03:03 by Phil

Last week saw the inaugural meeting of the London based F# user group – F#unctional Londoners. The group already has over 100 members! There were 2 talks Numerical Optimisation and Instant Messaging with F#, with Naoufel El Bachir giving a really good talk on Numerical Optimization and myself on Trading with Instant Messaging (IM). We had a great turn out, managing to fill the allocated room with around 50 F# enthusiasts, and there was some great discussion after both after the talks and then at a local pub.

A little positive feedback I’ve from the event :) :

loved your presentation on F#!

… that was awesome.

The slides from my Trading on IM talk will be attached to this post, and the video/podcast should be appear on the Skills Matter website. I’ll also attach the 100 lines of code for shopping checkout sample, that works with a barcode scanner, I showed at the start of my presentation.

In the talk I tried to introduce F# agents and asynchronous workflows. If you are interested in learning more please take a look at the following excellent resources:

Next week there is a very interesting talk to look forward to by Rob Pickering, author of Beginning F#, on Language Orientated Programming to target the GPU. And on the horizon we’re expecting in June to see Thomas Petricek, author (with Jon Skeet) of Real-world Functional Programming with examples in F# and C#. Finally, If you’d like to do a talk please do get in touch.

Trading on IM final.pptx (604.82 kb)

Checkout.zip (3.57 kb)


Tags:
Categories: .Net | F#
Actions: E-mail | Permalink | Comments (3) | Comment RSSRSS comment feed

UML Sequence Diagram: F# Script

April 26, 2010 23:55 by Phil

A UML Sequence diagram can be a great tool for modelling interaction:

UML sequence diagrams model the flow of logic within your system in a visual manner, enabling you both to document and validate your logic, and are commonly used for both analysis and design purposes.  Sequence diagrams are the most popular UML artifact for dynamic modeling, which focuses on identifying the behavior within your system.

Yesterday I fancied moving some hand drawn diagrams to mouse drawn form; but instead found myself battling against a somewhat stubborn and forgetful modelling tool. It left me wondering if there might be an easier way to do this; perhaps by separating the concern of model description from layout. A few moments later I had a description language using an F# class and an F# discriminated union:

type Object(name) =     
    member this.Name = name    

type SequenceAction =
    | Activate of Object
    | Deactivate of Object
    | MessageCall of string * Object * Object
    | MessageAsync of string * Object * Object

Together the Object and SequenceAction types describe an internal Domain Specific Language (DSL) for Sequence Diagrams.

The following is a simple restaurant sample definition (taken from Wikipedia) using the DSL:

let fred = Object("Fred\r\nPatron")
let bob = Object("Bob\r\nWaiter")
let hank = Object("Hank\r\nCook")
let renee = Object("Renee\r\nCashier")
let objects = [fred;bob;hank;renee]   
let actions = 
    [
    MessageCall("order food",fred,bob)
    MessageCall("order food",bob,hank)
    MessageCall("serve wine",bob,fred)
    MessageCall("pickup",hank,bob)
    MessageCall("serve food",bob,fred)
    MessageCall("pay",fred,renee)
    ]

 

Onto the layout, and the .Net Framework has the necessary batteries included to easily do this using either WPF or Silverlight with the:

To get started I used Visual Studio 2010’s WPF XAML designer for prototyping the layout. Then several hours of hacking later I had an F# script (attached) for drawing basic diagrams.

The following was generated using the simple restaurant description above:

simple restaurant uml sequence diagram sample

The colouring of the objects was achieved by extending the Object to allow arbitary dynamic properties to be set which can later be fed to the control:

type DynamicObject () =
    let properties = System.Collections.Specialized.HybridDictionary()
    member this.Item 
        with get (index:string) = properties.[index] 
        and set (index:string) (value:obj) = properties.[index] <- value
    member this.Items =        
        let keys = seq { for key in properties.Keys do yield key :?> string }
        let values = seq { for value in properties.Values do yield value }
        Seq.zip keys values

// Define dynamic lookup get and set operators
let (?) (o:DynamicObject) (property:string) = 
    o.[property]
let (?<-) (o:DynamicObject) (property:string) (value:'a) = 
    o.[property] <- value

type Object(name) =  
    inherit DynamicObject()   
    member this.Name = name    

 

The object’s background colours are set thus:

fred?Background <- Brushes.LightGreen
bob?Background <- Brushes.LightBlue
hank?Background <- Brushes.LightBlue
renee?Background <- Brushes.Pink

 

Conclusion

Whiteboard and paper are still probably the best tools for modelling sequence diagrams. However the DSL approach does have the advantage of allowing easy insertion of objects and messages without the pain of manual layout (constant erasing and redrawing).

Resources

SequenceDiagram.fsx (11.97 kb)


Tags:
Categories: .Net | Architecture | F# | UML
Actions: E-mail | Permalink | Comments (4) | Comment RSSRSS comment feed

Implementing IObservable and extending Observable

April 14, 2010 01:13 by Phil

Following on from my post yesterday on implementing loosely coupled events; the following somewhat longer F# sample provides a simple System.IObservable<T> implementation for event consumers. This means that the loosely coupled events can now be easily consumed like vanilla .Net events using the sweeter syntactic sugar of either the F# Observable module and/or the Reactive Extensions (Rx).

Also included are some helper functions for IObservable<T>. The first is tap, based on Ruby’s function of the same name, that lets you tap into an expression sequence for debugging, logging, etc. The next is invoke which is used to implement both delay and onDispatcher, and could be used to provide functions for running on a background thread, etc. May your events be loose and happening.

Happening event broking interfaces:

/// Encapsulates a triggerable instance
type ITriggerable<'a> =
    abstract member Trigger : 'a -> unit
    
/// Encapsulates an event that is both triggerable and observable    
type IHappen<'a> = 
    inherit ITriggerable<'a> 
    inherit System.IObservable<'a>
            
/// Encapsulates repository of IHappen instances
type IHappenings =
    abstract member ObtainHappening<'a> : unit -> IHappen<'a>

 

The Happening implementation:

/// Repository of IHappen instances      
type Happenings () =
    let happenings = System.Collections.Generic.Dictionary<System.Type,_>()
    let happeningsLock = obj()
    interface IHappenings with
        member this.ObtainHappening<'a> () =            
            let CreateHappening () = 
                let observers = ref []
                let add observer = 
                    observers := 
                        observer::!observers
                let remove observer = 
                    observers := 
                       !observers |> List.filter(fun x -> observer.Equals(x))
                let trigger x =
                    !observers 
                    |> List.iter (fun (observer:System.IObserver<'a>) -> 
                        observer.OnNext(x))
                let happenLock = obj()                        
                { new IHappen<'a> with                        
                    member this.Subscribe (observer:System.IObserver<'a>) =                                                                                    
                        lock happenLock (fun _ -> add observer)
                        { new System.IDisposable with
                            member this.Dispose() = 
                                lock happenLock (fun _ -> remove observer)                                
                        }                               
                    member this.Trigger (x:'a) = trigger x                       
                }               
            lock happeningsLock (fun _ ->    
                match happenings.TryGetValue(typeof<'a>) with
                | true, happen -> unbox happen
                | false, _ ->                 
                    let happen = CreateHappening ()
                    happenings.Add(typeof<'a>,box happen)
                    happen
            )                    
    end

 

Observable helper methods (tap, invoke, delay, onDispatcher):

/// Functions operating on IObservable<T>
module Observable = 
    open System
    open System.Windows.Threading
        
    /// Observer helper lifted from lib\FSharp.Core\control.fs
    [<AbstractClass>]  
    type BasicObserver<'a>() =
        let mutable stopped = false
        abstract Next : value : 'a -> unit
        abstract Error : error : exn -> unit
        abstract Completed : unit -> unit
        interface IObserver<'a> with
            member x.OnNext value = 
                if not stopped then x.Next value
            member x.OnError e = 
                if not stopped then stopped <- true
                x.Error e
            member x.OnCompleted () = 
                if not stopped then stopped <- true
                x.Completed ()
    
    /// Tap into a sequence of Observable expressions
    let tap f (w:IObservable<_>) =
        let hook (observer:IObserver<_>) =
            { new BasicObserver<_>() with  
                member x.Next(v) = 
                    match (try f v; None with | exn -> Some(exn)) with
                    | Some(exn) -> observer.OnError exn
                    | None -> observer.OnNext v                    
                member x.Error(e) = 
                    observer.OnError(e)
                member x.Completed() = 
                   observer.OnCompleted() 
            } 
        { new IObservable<_> with 
            member x.Subscribe(observer) =
                w.Subscribe (hook(observer))                    
        }
   
    /// Invoke Observer function through specified function
    let invoke f (w:IObservable<_>) =
        let hook (observer:IObserver<_>) =
            { new BasicObserver<_>() with  
                member x.Next(v) = 
                    f (fun () -> observer.OnNext v)
                member x.Error(e) = 
                    f (fun () -> observer.OnError(e))
                member x.Completed() = 
                    f (fun () -> observer.OnCompleted()) 
            } 
        { new IObservable<_> with 
            member x.Subscribe(observer) =
                w.Subscribe (hook(observer))
        }
 
    /// Delay execution of Observer function
    let delay milliseconds (observable:IObservable<'a>) =
        let f g =
            async {
                do! Async.Sleep(milliseconds)
                do g ()
            } |> Async.Start
        invoke f observable 
     
    /// Execture Observer function on Dispatcher thread
    /// <Remarks>For WPF and Silverlight</remarks> 
    let onDispatcher (observable:IObservable<'a>) =
        let dispatcher = Dispatcher.CurrentDispatcher
        let f g =
            dispatcher.BeginInvoke(Action(fun _ -> g())) |> ignore
        invoke f observable

 

To wrap up, Matthew Podwysocki’s Time Flies Like An Arrow in F# and the Reactive Extensions for .NET redux (Note: also worth checking Brian McNamara’s version):

module Test =  
    open System
    open System.Windows
    open System.Windows.Controls
    open System.Windows.Input
    open System.Windows.Media
    open System.Windows.Threading           
        
    let getPosition (element : #UIElement) (args : MouseEventArgs) =
        let point = args.GetPosition(element)
        (point.X, point.Y)    
     
    type TimeFliesWindow(happenings:IHappenings) as this =
        inherit Window()        

        let canvas=Canvas(Width=800.0,Height=400.0,Background=Brushes.White) 
        do this.Content <- canvas       

        do "F# can react to second class events!"
            |> Seq.iteri(fun i c ->  
                let s = TextBlock(Width=20.0, 
                                Height=30.0, 
                                FontSize=20.0, 
                                Text=string c, 
                                Foreground=Brushes.Black, 
                                Background=Brushes.White)
                canvas.Children.Add(s) |> ignore              
                // Consume mouse movement happenings                 
                happenings.ObtainHappening<MouseEventArgs>()                                 
                |> Observable.map (getPosition canvas)       
                |> Observable.tap (fun p -> Console.WriteLine p)
                |> Observable.delay (i * 100)
                |> Observable.onDispatcher
                |> Observable.subscribe (fun (x, y) ->                                                        
                     Canvas.SetTop(s, y) 
                     Canvas.SetLeft(s, x + float ( i * 10)))              
                |> ignore
           )        
              
    let happenings = new Happenings() :> IHappenings
    let win = TimeFliesWindow(happenings,Title="Time files like an arrow")   
    
    do  // Publish mouse movement event happenings
        let happen = happenings.ObtainHappening<MouseEventArgs>()
        win.MouseMove         
        |> Observable.subscribe happen.Trigger |> ignore

    [<STAThread>]
    do (new Application()).Run(win) |> ignore

Happening.fs (7.12 kb)


Tags:
Categories: .Net | F#
Actions: E-mail | Permalink | Comments (6) | Comment RSSRSS comment feed