Archive

Monthly Archives: January 2016

I recently learned how to implement ValueConverters in F#.

In case you haven’t realized, I have been experimenting with F# on my off time so that I can be a better developer and thus increase both my worth and influence within the software development industry.

ValueConverters serve as translators for data binding. Specifically, they convert values of one type to another type. Meaning that a property of one type within a viewmodel can be translated to a property of another type within a XAML file.

Suppose we had the following Domain:

module ManageModule.Entities
 
type Duration = { 
    Hours:int
    Minutes:int
    Seconds:int 
}
 
type String20 = String20 of string
 
type Name = { 
    First:String20
    Last:String20
    Suffix:String20 option 
}
 
type Module = { 
    Author:Name
    Duration:Duration 
}
 
and Section = 
    | Introduction of Module
    | Conclusion of Module
    | Content of Module list

 

Next, suppose we had the following viewmodel:

namespace ManageModules
 
    open System.Windows.Input
    open UILogic.State
    open UILogic.Interaction
    open ManageModule.Entities
    open System.Collections.ObjectModel
 
    type CreationViewModel() =
        inherit ViewModelBase()
 
        let mutable (_modules:Module ObservableCollection) = ObservableCollection()
 
        let name =       { First=String20("Scott"); Last=String20("Nimrod"); Suffix=None }
        let duration =   { Hours=1; Minutes=30; Seconds=0 }
        let moduleItem = { Author=name; Duration=duration }
 
        do _modules.Add(moduleItem)
 
        member this.Modules
            with get()     = _modules
            and set(value) = _modules <- value
 
        member this.Add moduleItem = 
            _modules.Add(moduleItem)

Then, suppose we had the following XAML:

<Window x:Class="Client.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Client"
        xmlns:manageModules="clr-namespace:ManageModules;assembly=ManageModules"
        xmlns:converters="clr-namespace:ManageModules.Converters;assembly=ManageModules"
        mc:Ignorable="d"
        Background="Black"
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <manageModules:CreationViewModel />
    </Window.DataContext>

    <Window.Resources>
        <converters:SomeValueConverter x:Key="SomeValueConverter" />
    </Window.Resources>

    <Grid>
        <ListView ItemsSource="{Binding Modules}" Background="Black">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Author.First, Converter={StaticResource SomeValueConverter}}"
                               Foreground="LightBlue" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

We could implement our ValueConverter like this:

namespace ManageModules.Converters

open System.Windows.Data
open ManageModule.Entities

type SomeValueConverter() =
    interface IValueConverter with
        member x.Convert(value, targetType, parameter, culture) = 
            let string20 = value :?> String20
            match string20 with String20 v -> v :> obj

        member x.ConvertBack(value, targetType, parameter, culture) = failwith "Not implemented yet"
Advertisements

Intro

I am learning F# and am logging my progress or lack of. In doing so, I attempted a Kata for implementing a string calculator.

I did steps 1-4 of the exercise. I then got bored and decided to look for other katas.

The following code was generated to satisfy the guts of the kata:

module Calculator

open FsUnit
open NUnit.Framework
open System

let add (numbers:string) =

    let add (numbers:string) (delimiters) =
        if numbers.Length = 0 then 0
        else numbers.Split(delimiters) |> Array.map Int32.Parse
                                       |> Array.sum
    let delimiters = [|',';'\n'|]
    let tokens = numbers.Split(delimiters);
    let lastToken = tokens.[tokens.Length-1]

    let valid = lastToken <> ""
    if valid then add numbers delimiters
    else 0

Here’s the tests that flushed out the code:

[<Test>]
let ``adding empty string returns zero`` () =

    let result = add ""
    result |> should equal 0

[<Test>]
let ``adding one number returns number`` () =

    let result = add "3"
    result |> should equal 3

[<Test>]
let ``add two numbers`` () =

    let result = add "3,4"
    result |> should equal 7

[<Test>]
let ``add three numbers`` () =

    let result = add "3,4,5"
    result |> should equal 12

[<Test>]
let ``line feeds embedded`` () =

    let result = add "3\n4"
    result |> should equal 7

[<Test>]
let ``1,\n will not be processed`` () =

    let result = add "1\n"
    result |> should equal 0

Conclusion

In conclusion, I am learning F# and am logging my progress or lack of. In doing so, I attempted a Kata for implementing a string calculator.

I did steps 1-4 of the exercise. I then got bored and decided to look for other katas.

Intro

I have been banging my head against the wall as I attempt to learn F#. This language is designed to simplify programming. F# reduces the amount of syntax required via declarative expressions instead over imperative statements.

Although I sincerely believe that F# is the future of .NET development, my mind is stuck on Object-Oriented design principles. As a result, I am forcing myself to either produce or absorb F# material everyday so that I can complete my transformation as a functional developer.

When I studied for my WPF certification, I decided to create a Checkers game. Hence, building a board game would demonstrate UX fundamentals via WPF. Thus, I implemented animations, styles, multitriggers, multibindings, routed events, and other features that the WPF framework provided.

I now find myself applying the same approach to F#. In my case though, I decided to build a Blackjack game. Thus, this experience has been very painful for me. I have never applied functional programming to business logic problems. For example, I have always used if-statements to dictate logical paths of execution. However, in F#, this is frowned upon.

BlackJack

The following application is a partial implementation of a Blackjack game. The languages used are XAML, F#, and C#. This partial implementation deals a “hand” and also a hit”.  In addition to the deal functions, the app also maintains the hand count. Please note that this is a partial implementation of a Blackjack game. The current implementation of this app does not yet satisfy the rules of Blackjack. For example, there is no implementation for “Bust”.  Furthermore, there is no implementation for an actual Blackjack game. Hence, this app only deals cards and maintains count.

The following is a screenshot of the app:

BlackJack

XAML

The XAML is fairly basic:

<Window x:Class="BlackJack.Client.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BlackJack.Client"
        mc:Ignorable="d"
        Title="Cards" Width="550">
    
    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    
    <Grid Background="Green">
        <Grid.RowDefinitions>
            <RowDefinition Height="2*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <ItemsControl Grid.Row="0" Grid.ColumnSpan="2" ItemsSource="{Binding Hand}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Image Source="{Binding}" Height="140" Margin="5" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

        <StackPanel Orientation="Horizontal" Margin="5">
            <TextBlock Text="Count:" FontSize="18" Foreground="DarkGreen" FontStyle="Italic" Margin="0,0,10,0"/>
            <TextBlock Text="{Binding Count}" FontSize="24" Foreground="LightGreen" FontWeight="Bold" />
        </StackPanel>
        
        <Button Grid.Row="1" Grid.Column="0" Content="Deal" Command="{Binding DealCommand}" Margin="5" />
        <Button Grid.Row="1" Grid.Column="1" Content="Hit" Command="{Binding HitCommand}" Margin="5" />
    </Grid>
</Window>

ViewModel

I usually partition my view-models into separate files. In this implementation, the view-model is a partial class, “ViewModel” and “ViewModel.internal”.

The following is the top-level view-model class:

using System.Collections.ObjectModel;
using Bizmonger.Patterns;
using Bizmonger.UILogic;

namespace BlackJack.Client
{
    public partial class ViewModel : ViewModelBase
    {
        public ViewModel()
        {
            HitCommand = new DelegateCommand(obj => OnHit());
            DealCommand = new DelegateCommand(obj => OnDeal());
        }

        ObservableCollection<string> _hand = new ObservableCollection<string>();
        public ObservableCollection<string> Hand
        {
            get
            {
                return _hand;
            }

            set
            {
                if (_hand != value)
                {
                    _hand = value;
                    OnPropertyChanged();
                }
            }
        }

        int _count;
        public int Count
        {
            get
            {
                return _count;
            }

            set
            {
                if (_count != value)
                {
                    _count = value;
                    OnPropertyChanged();
                }
            }
        }

        public DelegateCommand DealCommand { get; }
        public DelegateCommand HitCommand { get; }
    }
}

ViewModel.Internal

using Microsoft.FSharp.Collections;
using Microsoft.FSharp.Core;
using static BlackJack.Client.Constants;
using static Core;

namespace BlackJack.Client
{
    public partial class ViewModel
    {
        FSharpList<Card> _deck = shuffle(deck);

        void OnHit()
        {
            var cards = hitPlayer(_deck);
            Deal(new FSharpOption<Card>(cards.Item1), cards.Item2);
            Count += getFaceValue(cards.Item1.Face);
        }

        void OnDeal()
        {
            var result = deal(shuffle(deck));
            var hand = result.Item1;

            Deal(new FSharpOption<Card>(hand.Value.Item1), result.Item2);
            Deal(new FSharpOption<Card>(hand.Value.Item2), result.Item2);

            Count += getHandCount(hand);
        }

        void Deal(FSharpOption<Card> candidate, FSharpList<Card> deck)
        {
            var card = $"{DIRECTORY}{getFile(candidate)}";
            Hand.Accept(card);
            _deck = deck;
        }
    }
}
module Core

    open FsUnit
    open NUnit.Framework
    open Microsoft.FSharp.Reflection

    let GetUnionCaseName(x:'a) =
        match FSharpValue.GetUnionFields(x, typeof<'a>) with
        | case, _ -> case.Name

    type Suit = | Spades| Clubs | Diamonds | Hearts
 
    type Face = | Two | Three | Four | Five 
                | Six | Seven | Eight | Nine | Ten
                | Jack | Queen | King | Ace
 
    type Card = {Face:Face; Suit:Suit}
 
    type Deal = | Hand of Card * Card
                | Hit of Card

    let private suits = [Spades; Clubs; Diamonds ; Hearts]

    let private faces = [Two; Three; Four; Five; Six; Seven; Eight; Nine; Ten;
                         Jack; Queen; King; Ace]
 
    let deck = [for suit in suits do
                    for face in faces do
                        yield {Face=face; Suit=suit}]
 
    let hitPlayer (deck:Card list) =
        (deck.Head, deck.Tail)
 
    let shuffle xs =
        let swap i j (array : _[]) =
            let tmp = array.[i]
            array.[i] <- array.[j]
            array.[j] <- tmp
        let rnd = System.Random()
        let xArray = Seq.toArray xs
        let n = Array.length xArray
        for i in [0..(n-2)] do
            let j = rnd.Next(i, n-1)
            swap i j xArray
        xArray |> Seq.toList

    let deal = function
        | card1::card2::remaining -> Some(card1, card2), remaining
        | _ -> None, [];;

    let getFile card =
        let digitize (candidate:string) =
            let formatted = candidate.ToLower()
            match formatted with
            | "two" -> "2"
            | "three" -> "3"
            | "four" -> "4"
            | "five" -> "5"
            | "six" -> "6"
            | "seven" -> "7"
            | "eight" -> "8"
            | "nine" -> "9"
            | "ten" -> "10"
            | _ -> candidate

        match card with
        | Some c ->
            let face = c.Face |> GetUnionCaseName |> digitize
            let suit = c.Suit |> GetUnionCaseName
            sprintf "%s_of_%s.png" face suit
        | None -> ""

    let getCard(hand:((Card*Card) Option), position:int) =
        match position with
        | 1 -> hand |> Option.map fst |> getFile
        | 2 -> hand |> Option.map snd |> getFile
        | _ -> ""

    let mapIdToType (text:string) =
        let delimited = text.Split '_'
        let face = delimited.[0]
        let suit = delimited.[(delimited.Length - 1)]
        face, suit

    let getFaceValue = function
        | Two -> 2
        | Three -> 3
        | Four -> 4
        | Five -> 5
        | Six -> 6
        | Seven -> 7
        | Eight -> 8
        | Nine -> 9
        | Ten -> 10
        | Jack -> 10
        | Queen -> 10
        | King -> 10
        | Ace -> 11

    let getCount (hand:Card list) =
        hand |> List.sumBy (fun c -> getFaceValue c.Face)

    let getHandCount = function
        | Some(card1, card2) -> [card1; card2] |> getCount
        | None -> 0

Conclusion

In conclusion, I have been banging my head against the wall as I attempt to learn F#. This language is designed to simplify programming. F# reduces the amount of syntax required via declarative expressions instead of imperative statements. I have provided a partial implementation of Blackjack using WPF, C#, and F#.