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

Silverlight 4 Calculator Sample in F#

June 7, 2010 14:07 by Phil

If you have Silverlight 4 installed you should see a calculator sample below coded in F#. The sample originally targeted WPF, only a few modifications were required to run in Silverlight:

  • the view is hosted in a UserControl instead of a Window
  • a C# project is used to launch the UserControl and generate the Silverlight XAP file

The sample demonstrates creating a View in WPF or Silverlight without XAML. The idea is to make things a little easier from F# by implementing a (+) operator overload to attach dependency properties.

The following snippet shows the keypad being constructed by transforming tuples describing the key character and action to buttons:

let keys =
    let grid = new Grid()
    for i = 1 to 4 do
        ColumnDefinition() |> grid.ColumnDefinitions.Add 
        RowDefinition() |> grid.RowDefinitions.Add
    [ 
    ['7',Digit(7);'8',Digit(8);'9',Digit(9);'/',Operator(Divide)]
    ['4',Digit(4);'5',Digit(5);'6',Digit(6);'*',Operator(Multiply)]
    ['1',Digit(1);'2',Digit(2);'3',Digit(3);'-',Operator(Minus)]
    ['0',Digit(0);'.',Dot;'=',Evaluate;'+',Operator(Plus)]
    ]    
    |> List.mapi (fun y ys ->
        ys |> List.mapi (fun x (c,key) ->
            let color =
                match key with
                | Operator(_) | Evaluate -> Colors.Yellow
                | Digit(_) | Dot -> Colors.LightGray                        
            let effect =
                Binding("Operator",
                        Converter=operationEffectConverter,
                        ConverterParameter=key)    
            Button(Content=c,CommandParameter=key,
                Width=40.0,Height=40.0,Margin=Thickness(4.0),
                Background=SolidColorBrush(color)) +                
                Button.CommandBinding(Binding("KeyCommand")) +
                Button.EffectBinding(effect) +
                Grid.Column(x) + Grid.Row(y)                         
        )
    )
    |> List.concat
    |> List.iter (grid.Children.Add >> ignore)
    grid

 

Note: This article is more a thought experiment in trying F# code instead of XAML to describe a View. In many cases XAML with a C#/F# View Model may be the pragmatic choice.

PS There is a very concise WebSharper F# Calculator sample, that generates JavaScript.

SilverlightCalculator.zip (10.09 kb)


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

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

MVMMC – MVVM grows a Controller

May 19, 2010 15:27 by phil

Ray Booysen does it again! The first time I saw Ray do a talk was at NxtGen in Cambridge, when he gave me a timely introduction to MVVM just as I was starting to play with WPF. MVVM (Model-View-View Model) is an architectural pattern, that improves on code behind, making it possible to unit test your UI code (View Model), a good thing. Over a year later and I’m just starting to play with Silverlight, Ray delivers another timely talk on Silverlight gotchas at the Edge UG in London, based on his real-world development experience (developing Financial applications). This time he introduces among other good things MVVMC (MVVM plus Controller). Here the controller takes responsibility for communication between the Model and View Model, leaving the View Model with the single responsibility of providing data to the View.

Somewhat shell shocked I was left with a few questions on implementation details, again Ray to the rescue via Twitter:

ptrelford Excellent @raybooysen Silverlight gotchas talk - MVVMC (C for controller), Network is on UI thread, browser connection limits #edgeug

ptrelford @raybooysen really liked Fat Controller slide, of Thomas the Tank Engine; controller takes responsiblity for marshalling threads etc #edgeug

raybooysen @ptrelford fat controller should be in all slide decks. :)

raybooysen Talk finished at @edge_ug. Think it went ok. Feel like I rambled a little.

ptrelford So with MVVMC the Model is observed by a Controller, which constructs & updates a View Model, which the (XAML) View binds to

raybooysen @ptrelford thanks for coming tonight. :)

ptrelford @raybooysen using MVVMC the Controller observes the Model & updates View Model, which observes user input and passes messages to the Model?

raybooysen @ptrelford viewmodel observes and notifies the the controller.

ptrelford @raybooysen thanks! So View Model takes a reference to the parent controller?

raybooysen @ptrelford no. Can surface the ui interaction via events. Or use rx if you're in for some fun.

ptrelford @raybooysen Cool thanks again! That makes sense, View Model exposes IObservable<T> properties. BTW your talk blew me away (hence questions)!

raybooysen @ptrelford no worries. Iobservable feels quite right in these scenarios. Since controller essentially owns the viewmodel

Finally, this was the same talk that Ray delivered at DDD Scotland, so the slides are already available here

image

image

image

 

image


Tags:
Categories: C# | .Net | Architecture | WPF | Silverlight
Actions: E-mail | Permalink | Comments (2) | 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

What’s happening? Loosely coupled events

April 13, 2010 01:37 by phil

So the Reactive Extensions (Rx) demonstrate some sweet syntax for handling CLR events. How about doing the same thing for loosely coupled events exposed through an Event Broker like Prism’s IEventAggregator. For example if you wanted to publish an event from any window that could be observed by any other window without them all having intimate knowledge of each other.

The following is a simple F# event broker coded on the train this morning (Note: the interface ISubscribe<’a> could be replaced by IObservable<’a>):

type ITrigger<'a> =
    abstract member Trigger : 'a -> unit
    
type ISubscribe<'a> =     
    abstract member Subscribe : ('a -> unit) -> unit 

type IHappen<'a> = 
    inherit ITrigger<'a> 
    inherit ISubscribe<'a>
            
type IHappenings =
    abstract member ObtainHappening<'a> : unit -> IHappen<'a>
        
type Happenings () =
    let happenings = System.Collections.Generic.Dictionary<System.Type,_>()
    interface IHappenings with
        member this.ObtainHappening<'a> () =
            let CreateHappening () = 
                let subscribers = ref []
                { new IHappen<'a> with                        
                    member this.Subscribe f = 
                        lock(this) (fun _ -> 
                            subscribers := f::!subscribers)
                    member this.Trigger (x) =                      
                        !subscribers |> List.iter (fun f -> f x)                       
                }
            lock (this) (fun _ ->    
                match happenings.TryGetValue(typeof<'a>) with
                | true, happen -> unbox happen
                | false, _ ->                 
                    let happen = CreateHappening ()
                    happenings.Add(typeof<'a>,box happen)
                    happen
            )                    
    end

 

Then, in Starbucks for a coffee and some higher-order functions :

module Happening =   
    open System
    open System.Windows.Threading

    let Subscribe<'a> f (happening:ISubscribe<'a>) =         
        happening.Subscribe f
    let OnDispatcher<'a> (happening:ISubscribe<'a>) =
        let dispatcher = Dispatcher.CurrentDispatcher
        { new ISubscribe<'a> with  
            member this.Subscribe f = 
                happening.Subscribe (fun x -> 
                dispatcher.Invoke(Action(fun _ -> f x)) |> ignore
            )            
        }        
    let Filter<'a> filterF (happening:ISubscribe<'a>) =
        { new ISubscribe<'a> with  
            member this.Subscribe f = 
                happening.Subscribe (fun x -> if filterF x then f x)          
        }
    let Map<'a,'b> mapF (happening:ISubscribe<'a>) =        
        { new ISubscribe<'b> with  
            member this.Subscribe f = 
                happening.Subscribe (fun x -> let y = mapF x in f y)            
        }
    let Delay<'a> milliseconds (happening:ISubscribe<'a>) =
        { new ISubscribe<'a> with  
            member this.Subscribe f = 
                happening.Subscribe (fun x -> 
                    async { 
                        do! Async.Sleep(milliseconds) 
                        f x 
                    } |> Async.Start )            
        }

 

Finally, here is Matthew Podwysocki’s cool Time Flies Like An Arrow sample rewritten to use more loosely-coupled events:

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

        do this.Title <- "Time files like an arrow"

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

        let happen = happenings.ObtainHappening<MouseEventArgs>()
        do this.MouseMove         
            |> Observable.subscribe happen.Trigger |> ignore

        do "F# can react to first 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              
                happen                  
                |> Happening.Map (getPosition canvas)           
                |> Happening.Delay (i * 100)
                |> Happening.OnDispatcher                            
                |> Happening.Subscribe (fun (x, y) ->                                                        
                     Canvas.SetTop(s, y) 
                     Canvas.SetLeft(s, x + float ( i * 10)))              
           )        
              
    let happenings = new Happenings()
    let win = TimeFliesWindow(happenings)
    [<STAThread>]
    do (new Application()).Run(win) |> ignore

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