WinRT XAML Validation library: UI Controls for Validation

After you’ve defined the validation logic for your entities and performed validation automatically or manually, you want to show the aggregated validation messages on the UI. Unfortunately WinRT/XAML doesn’t come with such a functionality out of the box and solutions like Prism for Windows Runtime don’t add much value here as well.

WinRT XAML Validation library to the rescue: it comes with two handy UI controls ValidationPanel and ValidationSummary that give you a generic and easy-to-use approach to show validation messages to the user.

ValidationPanel

The ValidationPanel control can be used to show validation information for a single property of your data model entity. It can be wrapped around any XAML control (e.g. a TextBox) and has the following abilities:

  • Show a red/yellow border around the control to represent Errors/Warnings.
  • Show all validation messages for a property at the bottom of the control (optionally).

The usage of the ValidationPanel is quite simple. In XAML, just wrap it around a normal UI control and bind the ValidationMessages collection with the corresponding entity property as key to the control’s ValidationSource property:

<Page x:Class="WinRTXAMLValidation.Demo.MainPage" ...
      xmlns:vc="using:WinRTXAMLValidation.Library.Controls">
    ...
    <TextBlock Text="Your bid" />
    <vc:ValidationPanel ValidationSource="{Binding Bid.ValidationMessages[NewBid]}">
        <TextBox Text="{Binding Bid.NewBid, Mode=TwoWay}" />
    </vc:ValidationPanel>
</Page>

Here’s a sample output of two ValidationPanel controls, showing warnings and errors for the wrapped user inputs:

There are several properties on ValidationPanel that define its behavior:

  • ValidationSource: Bind any ReadOnlyCollection<ValidationMessage> to this property and the control will display the corresponding validation messages (Errors/Warnings). Normally binds to ValidationBindableBase.ValidationMessages[<PropertyName>].
  • ShowValidationMessages (default: true): Indicates whether the validation message texts will be shown on the control. Otherwise, only a red/orange border will be drawn on error/warning validation messages.
  • ShowPropertyValidationMessages (default: true): Indicates whether simple validation messages for a property (identified by ValidationMessage.ValidationMessageKind.Property) will be shown as text at the control.
  • ShowGroupValidationMessages (default: true): Indicates whether property-group validation messages (identified by ValidationMessage.ValidationMessageKind.Overall) will be shown as text at the control. This can come in handy if you don’t want to use the ValidationPanel for validation messages that span several properties, but show them in the aggregating ValidationSummary instead.

If you’ve used manual validation with a fake entity that stores the validation messages for you, you can bind the fake entity to ValidationPanel and your data model entity to the wrapped control as before:

<vc:ValidationPanel ValidationSource="{Binding BidValidation.ValidationMessages[NewBid]}">
    <TextBox Text="{Binding Bid.NewBid, Mode=TwoWay}" />
</vc:ValidationPanel>

 

ValidationSummary

The second control of the WinRT XAML Validation library is the ValidationSummary. While the ValidationPanel can be used to show validation messages for a single property, the ValidationSummary is there to show all aggregated validation messages of an entity.

Usage of the ValidationSummary is very easy. Just bind its ValidationSource property to ValidationBindableBase.ValidationMessages.AllMessages, if your entity derives from ValidationBindableBase. Moreover, you can use any ReadOnlyDictionary<string, ReadOnlyCollection<ValidationMessage>> of validation messages for the properties of an entity and bind it to the control. Here’s a simple code example:

<Page x:Class="WinRTXAMLValidation.Demo.MainPage" ...
      xmlns:vc="using:WinRTXAMLValidation.Library.Controls">
    ...
    <vc:ValidationSummary ValidationSource="{Binding Bid.ValidationMessages.AllMessages}" Header="General input errors" />
</Page>

The following picture shows a sample output of the ValidationSummary for a validated entity, including errors and warnings.

There are several properties of the control that can be used to define its behavior:

  • ValidationSource: Dictionary of validation messages that should be shown in the summary. Normally binds to ValidationBindableBase.ValidationMessages.AllMessages.
  • ShowPropertyValidationMessages (default: true): Indicates whether validation messages for single properties should be shown in the summary or not.
  • ShowGroupValidationMessages (default: true): Indicates whether validation messages for property groups should be shown in the summary or not. This can come in handy, if you want to show this information only in ValidationPanel, but not in the ValidationSummary.
  • AffectedPropertyNames: Collection of property names, whose validation messages should be shown in the summary. If no value is given, the validation messages for all properties will be shown.
  • Header: Header text to be shown above the summary. If no value is given, no header will be shown.
  • ShowHeader (default: true): Indicates whether a header will be shown above the summary or not.

 

WinRT XAML Validation library: Manual Validation

Defining validation logic using Data Annotations is the default and recommended way in the WinRT XAML Validation library. But of course there are good reasons that you don’t want to use this approach. For example, you want to have all the validation logic for an entity at a central place or you don’t want your entities to implement ValidationBindableBase or you even don’t have access to the data model entities.

In this case you have the possibility to bypass the validation attributes and the ValidationBindableBase base class for your model entities. You get the flexibility to perform validation for yourself and add validation messages to the storage dictionaries.

Implement ValidationBindableBase

What you need is some entity that implements ValidationBindableBase and thus acts as store for the validation messages. Normally, this would be your “real” model entity, but you’re able to define a fake entity as well. The only purpose of this entity is to store the validation messages through ValidationBindableBase, so this information can be bound to the UI. In the following example you can see a fake entity AuctionBidValidation that stores the validation messages for the original data model entity AuctionBid. The advantage: you don’t have to change your data model entity to derive from ValidationBindableBase:

public class AuctionBid
{
    public double CurrentBid { get; set; }
    public double NewBid { get; set; }
    public double? MaxNewBid { get; set; }
}

public class AuctionBidValidation : ValidationBindableBase { }

public class MainViewModel : BindableBase
{
    public AuctionBid Bid { get; private set; }
    public AuctionBidValidation BidValidation { get; private set; }
}

The view model contains the “real” data model entity as well as the validation storage for the entity. Now both properties are exposed and can be bound to the UI. An upcoming blog post will show you how this happens.

Manually add validation messages

After you’ve performed validation for yourself, you can add a new validation message using ValidationBindableBase.ValidationMessages.AddMessage(). There are two overloads of this method: with the first you can add a validation message to a property, with the second you add a validation message for the whole entity. The following code example shows manual validation and adding validation messages manually:

public async Task SendBidAsync(AuctionBid bid, AuctionBidValidation bidValidation)
{
    bidValidation.ValidationMessages.ClearMessages();

    if (bid.MaxNewBid.HasValue && bid.NewBid > bid.MaxNewBid)
    {
        bidValidation.ValidationMessages.AddMessage(
            () => bid.NewBid, ValidationLevel.Error,
            "New bid can not be higher than max new bid.");
    }

    if (bid.NewBid >= bid.CurrentBid * 100)
    {
        bidValidation.ValidationMessages.AddMessage(
            () => bid.NewBid, ValidationLevel.Warning,
            "Your bid surpasses the current bid by a 100 times.");
    }

    if (bid.NewBid <= await this.GetCurrentBidAsync(bid))
    {
        bidValidation.ValidationMessages.AddMessage(
            ValidationLevel.Error, "Your bid has been surpassed.");
    }

    ...
}

Look how the original data model entity and the fake validation entity work together to get the validation information. The fake validation entity just stores the validation messages. The following screenshot shows how those validation messages will be shown on the UI:

 

Clearing old validation messages

Before you start a new validation, make sure to clear the old validation messages by using the ValidationBindableBase.ValidationMessages.ClearMessages() method as shown in the example above.

 

And a final hint: When you use manual validation and leave the validation attributes behind, you loose the ability of automatic implicit and explicit user input validation. You should be aware of this, when you decide which validation option is the best for you. Of course you can mix automatic and manual validation, performing manual validation only in critical situations like saving an entity.

WinRT XAML Validation library: Implicit and Explicit Validation Execution

Now that you have defined all your validation attributes on your model classes, you want to perform validation to detect if your entity is valid or not. Here you can go two ways with the WinRT XAML Validation library: implicit validation validates your entity automatically when properties change, while with explicit validation you call a function to perform the validation.

Validatable model classes

A prerequisite to perform validation on a model entity with the WinRT XAML Validation library is that your model class derives from the ValidationBindableBase class. This class stores all validation messages for you and is able to perform validation on your entity:

public class AuctionBid : ValidationBindableBase { ... }

Implicit Validation Execution

Implicit validation is triggered automatically when an entity property changes, thus the setter is called. Implicit validation is an opt-in mechanism, meaning that you have to activate this functionality first before your entity gets validated. Just set the IsImplicitValidationEnabled property on your model entity that derives from ValidationBindableBase to true:

var bid = new AuctionBid();
bid.IsImplicitValidationEnabled = true;

If you want to disable implicit validation execution temporarily, you are able to set IsImplicitValidationEnabled=false at any time. Finally for implicit validation to fire, you have to implement your model properties explicitly with a backing field. In the property’s setter, you’ve to call the SetProperty() method from the base class ValidationBindableBase, which performs the validation of the matching attributes for the property:

[ValidateAgainstMaxBid(ShowMessageOnProperty = false)]
public class AuctionBid : ValidationBindableBase
{
    private double newBid;

    [Range(0, double.MaxValue, ErrorMessage = "Value must be greater 0.")]
    [ValidateGreaterCurrentBid]
    public double NewBid
    {
        get { return this.newBid; }
        set { base.SetProperty(ref this.newBid, value); }
    }

    ...
}

Explicit Validation Execution

In many situations you don’t want to execute implicit validation everytime a property changes. For this case the WinRT XAML Validation library gives you the ability to execute validation explicitly by calling the ValidationBindableBase.ValidateAsync() method. Because ValidationBindableBase will be the base class for your model entities, that means calling the method on the entity itself:

var bid = new AuctionBid();
...
bool isValid = await bid.ValidateAsync();

The method returns true if the entity is valid and false otherwise. It’s async because of the async validation ability of attributes from the WinRT XAML Validation library.

WinRT XAML Validation library: Async Validation Attributes

Last posts have shown how basic validation attributes and property-group based validation attributes can be used to define custom validation logic, that goes beyond the default capabilities of Data Annotations. There’s another validation attribute base class in the WinRT XAML Validation library and that’s the AsyncValidationAttribute and its sister, the AsyncGroupValidationAttribute.

Both attributes define the abstract method IsValidAsync(), which you can use in your derived validation attribute classes to perform asynchronous operations during validation. The following code gives an example for the AsyncValidationAttribute class:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class ValidateActualCurrentBidAttribute : AsyncValidationAttribute
{
    protected override async Task<ValidationResult> IsValidAsync(object value, ValidationContext validationContext)
    {
        var newBid = (double)value;
        var auctionBid = (AuctionBid)validationContext.ObjectInstance;
            
        var service = new AuctionService();
        var currentBid = await service.GetCurrentBidAsync(auctionBid);

        return (newBid > auctionBid.CurrentBid && newBid <= currentBid)
            ? new ValidationResult("Your bid has been surpassed.")
            : ValidationResult.Success;
    }
}

This sample async validation attribute calls the async service method AuctionService.GetCurrentBidAsync() to retrieve actual data from a server. It gets await’ed and returns the validation result after the async operations has returned. Thus you’re able to define custom validation logic in our asynchronous app world.

AsyncGroupValidationAttribute is a specialization of AsyncValidationAttribute, its usage doesn’t differ, so I will not show it here. The usage of an async validation attribute equals the usage of any other attribute on your entity and you’re able to use the functionality of the ExtendedValidationAttribute.

public class AuctionBid : ValidationBindableBase
{
    [ValidateActualCurrentBid(UseInImplicitValidation = false)]
    public double NewBid { ... }
}

WinRT XAML Validation library: Property-Group Validation Attributes

All predefined validation attributes in the System.ComponentModel.DataAnnotations namespace can be used to annotate a single property of an entity. So they cannot be used for validation that spans multiple properties.

For this case, the WinRT XAML Validation library comes with the GroupValidationAttribute base class. Its member CausativeProperties can be used to define properties, which cause the validation to run, when their values are changing. With the member AffectedProperties you can set properties, that will be marked invalid when the validation of a property from the CausativeProperties group fails.

The following code gives an example of a concrete validation class that extends the GroupValidationAttribute base class. CausativeProperties equals AffectedProperties, thus the group of properties that cause the validation equals the group of properties that are affected by the validation:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class ValidateAgainstMaxBidAttribute : GroupValidationAttribute
{
    protected override IEnumerable<Expression<Func<object>>> AffectedProperties
    {
        get
        {
            AuctionBid entity = null;
            return new Expression>[]
                {
                    () => entity.NewBid,
                    () => entity.MaxNewBid
                };
        }
    }

    protected override IEnumerable<Expression<Func<object>>> CausativeProperties
    {
        get { return this.AffectedProperties; }
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var auctionBid = (AuctionBid)validationContext.ObjectInstance;

        return auctionBid.MaxNewBid.HasValue && auctionBid.NewBid > auctionBid.MaxNewBid.Value
            ? new ValidationResult("New bid must not be greater than highest bid.")
            : ValidationResult.Success;
    }
}

This group validation property can now be used to annotate the whole model entity on class level:

[ValidateAgainstMaxBid(ShowMessageOnProperty = false)]
public class AuctionBid : ValidationBindableBase
{
    public double CurrentBid { ... }
    public double NewBid { ... }
    public double? MaxNewBid { ... }
}

Additionally, the GroupValidationAttribute class derives from the ExtendedValidationAttribute class, so you’re able to use additional functionality brought by the ValidationLevel,  ShowMessageOnProperty and ShowMessageInSummary properties and others.

WinRT XAML Validation library: Basic Validation Attributes

Validation in the WinRT XAML Validation library is mainly based on .NET Data Annotations from the System.ComponentModel.DataAnnotations namespace. Here you can find several attributes, that you can attach to your entities and its properties. This annotates them with additional information/metadata, which’s evaluated elsewhere in your code or by the .NET framework.

WPF, Silverlight and e.g. ASP.NET MVC can evaluate those attributes automatically to display further information for an entity like a property label, etc.. And you can define validation logic with Data Annotations on your entity, which gets evaluated and presented to the user when the entity is validated.

ValidationAttribute

The WinRT XAML Validation library uses the Data Annotations approach as well to define validation logic on model entities. First you can use the already defined validation attributes from the System.ComponentModel.DataAnnotations namespace: RangeAttribute, RegularExpressionAttribute, RequiredAttribute, StringLengthAttribute, CustomValidationAttribute. All of those predefined attributes implement the ValidationAttribute base class. You can derive from this class as well to implement validation attributes with your encapsulated custom validation logic, for example:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class ValidateGreaterCurrentBidAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var newBid = (double?)value;
        var auctionBid = (AuctionBid)validationContext.ObjectInstance;

        return newBid.HasValue && newBid.Value <= auctionBid.CurrentBid
            ? new ValidationResult("Value must be greater than current bid")
            : ValidationResult.Success;
    }
}

Now you can easily decorate your model entities with this attribute:

public class AuctionBid : ValidationBindableBase
{
    private double currentBid;
    private double newBid;
    private double? maxNewBid;

    public double CurrentBid
    {
        get { return this.currentBid; }
        set { this.SetProperty(ref this.currentBid, value); }
    }

    [Range(0, double.MaxValue, ErrorMessage = "Value must not be negative")]
    [ValidateGreaterCurrentBid]
    public double NewBid
    {
        get { return this.newBid; }
        set { this.SetProperty(ref this.newBid, value); }
    }

    [ValidateGreaterCurrentBid]
    public double? MaxNewBid
    {
        get { return this.maxNewBid; }
        set { this.SetProperty(ref this.maxNewBid, value); }
    }
}

 

ExtendedValidationAttribute

With the abstract ExtendedValidationAttribute class there’s another base validation attribute in the WinRT XAML Validation library that extends the functionality of the ValidationAttribute. Specifically with this base class you can:

  • define a level for the validation message (Warning or Error)
  • define if the validation message should be shown on the property and in the validation summary on the UI
  • define if the validation attribute should be considered in implicit validation (when a property changes)

For example, a validation level “Warning” leads to the following output on the UI:

The definition on the entity property (taking a custom validation attribute ValidatePossibleMisentryBid as example) looks as follows:

[ValidatePossibleMisentryBid(ValidationLevel = ValidationLevel.Warning)]
public double NewBid { ... }

Like the ValidationAttribute you can use the ExtendedValidationAttribute as base class for your custom validation attributes.

WinRT XAML Validation library: Getting Started

This little blog posts describes how you can include the WinRT XAML Validation library in your project and get it to work.

Download

First go to the WinRT XAML Validation Codeplex project page and download the latest bits. The download package includes the sources of the library as well as a demo project (Windows Store App), which showcases many of the concepts and features of the library:

 

Usage by Source

To use the WinRT XAML Validation library, you have two possibilities. The first one is to include the library sources. To do this, copy the WinRTXAMLValidation.Library project to your app’s solution folder and add the existing WinRTXAMLValidation.Library.csproj project to your solution.

Add a reference to the library project everywhere you want to use the validation functionality. To get the UI control to work properly, you have to include the ValidationStyles.xaml file from the Styles folder of the library in your project. There are two different ways to do this:

  • Copy the ValidationStyles.xaml file to your Windows Store App project and reference it as ResourceDictionary in your App.xaml.
  • Add the ValidationStyles.xaml file as link in your Windows Store App project and reference it as ResourceDictionary in your App.xaml.

You’re free to choose from these approaches. Go the “copy way” if you want to adapt the validation styles to your needs. Go the “add as link” way if you simply want to use the UI controls as they are.

Usage by Assembly

If you don’t want to include the library’s sources to your solution, you can just add the compiled assembly as reference. To do this, first compile the WinRT XAML Validation library as Debug or Release. Copy the output assembly to your solution and reference it in every project where you want to use the validation functionality.

Copy the ValidationStyles.xaml file from the Styles folder of the library to your Windows Store App project and reference it as ResourceDictionary in your App.xaml.

Introducing the WinRT XAML Validation library

In this article I’m going to introduce “WinRT XAML Validation”, a library that brings consistent validation of user input to WinRT/C#/XAML apps. Upcoming blog posts will cover several aspects of the library in depth.

Prologue

I like WinRT. I like its approach of bringing common functionality to very different languages. But WinRT is not perfect. At least in “version 1″ (shipped with Windows 8 ) it has several shortcomings in various parts.

One of those shortcomings is user input validation in C#/XAML Windows Store Apps. Of course there are Data Annotations in .NET 4.5 for WinRT and the ValidationAttribute, also the INotifyDataErrorInfo interface is available. But what’s missing is the whole UI stuff. There are no UI controls or attributes on existing UI controls to show errors for validated properties. Hence at the moment you’re forced to execute validation manually and react accordingly to update the UI state.

“WinRT XAML Validation” library

I’ve been unsatisfied with this lack of support for complete user input validation in WinRT/XAML. Thus a colleague and I developed a library, that fills the missing pieces and goes beyond trivial validation tasks. We needed comfortable and extended validation functionality for one of our development projects and now we want to make the resulting bits available as easy-to-use library.

WinRT XAML Validation has a project page on Codeplex and is free-to-use under the Ms-PL license.

>> Codeplex Project Page <<

Functionality Overview

The WinRT XAML Validation library is aimed to give developers a consistent, flexible and easy-to-use library to perform user input validation in WinRT/XAML apps. Developers should get a generic approach, that guides them through all steps of validating user input and performs the work for them.

With the WinRT XAML Validation library, you get a whole bunch of functionality, including:

  • Validation Attributes: Define custom validation logic with Data Annotations on your model entities. The library contains extended base attributes for validation with support of warnings/errors, async validation and validation logic, that spans more than one property.
  • Implicit Validation Execution: Use the ValidationBindableBase class on your model entities to perform validation. You can opt-in to let validation execute automatically when a entity property changes (implicit validation).
  • Explicit Validation Execution: Instead of running validation everytime a property changes on your model entities, you can call the ValidationBindableBase.ValidateAsync() method explicitly to validate the defined validation attributes.
  • Manual Validation: Besides the use of validation attributes to define validation logic, you can easily perform custom validation logic and add corresponding validation messages to a Dictionary, using the ValidationBindableBase.ValidationMessages.Add() method. The provided UI controls will update themselves automatically.
  • Validation UI Controls: There are two easy-to-use XAML UI controls to show validation messages. First there is the ValidationPanel control that wraps a control whose bound property should be validated (for example a TextBox). If validation fires for the property, the ValidationPanel will show a red border (orange for warnings) and optionally the validation message. More than one validation message is supported. The second control is the ValidationSummary, which can show aggregated validation messages for a whole form and its bound entity. Both controls update immediately when validation messages change, even in async scenarios.

Credits

I want to give credit to the Patterns and Practices group at Microsoft for developing and releasing the Prism for Windows Runtime library (f.k.a. Kona). It’s an awesome library that adds much value to the development of WinRT apps and I encourage you to check it out if you’re serious about Windows 8 business app development.

Basic ideas and concepts for the WinRT XAML Validation library are borrowed from Prism for WinRT. For example, the BindableValidator class has been taken over, but includes much more functionality now. While Prism for WinRT comes with some validation bits, WinRT XAML Validation comes with a more complete approach to user input validation.

C# 4.0 Neuerungen

Die ersten Neuerungen kurz in 3 Stichpunkten:

  • Aufruf dynamischer Sprachen: dynamic-Schlüsselwort
  • Optionale Funktionsparameter wie in C++ (wie ich das vermisst habe!)
  • Rückgabe anonymer Typen durch Funktionen

Einen umfassenden Überblick über die Neuerungen gibt ein Word-Dokument, welches Microsoft hier zum Download bereitstellt.

Links:

Ein Blick auf F#

Funktionale Programmierung hat mich bereits während des Studiums beschäftigt, allerdings eher am Rande in Lehrveranstaltungen wie “Objektorientierte Konzepte”, wo in den Übungen Haskell gepredigt wurde. Teils verwirrt, teils fasziniert von dieser Art zu denken und zu programmieren hat mich das Thema nie richtig losgelassen und erlebt gerade einen persönlichen Aufschwung durch F#. F# ist Microsoft’s funktionale .NET Programmiersprache, die wie viele Innovationen Microsoft Research entsprungen ist. Es ist explizit hervorzuheben, dass F# das .NET-Framework als Basis nutzt. Demzufolge stehen auch alle Bibliotheken zur Verfügung, welche .NET so mächtig machen. Doch genug der Vorrede, los geht es mit F#. Ein kleiner Praxistest soll an dieser Stelle erste Eindrücke vermitteln…

Los geht’s…

Die aktuelle F# CTP kann auf der zugehörigen MSDN-Seite herunter geladen werden. Hier stehen auch weitere Ressourcen zur Verfügung, die beim Einstieg in die neue Programmiersprache behilflich sind. Flux installiert lässt sich im Visual Studio bei der Erstellung eines neuen Projekts der Punkt “Visual F#” wählen. Die ersten Zeilen Code sind bekanntlich die schwersten in jeder Programmiersprache, und doch halfen mir bereits hier meine ersten Erfahrungen in Haskell. Der große Unterschied: F# ist keine rein funktionale Programmiersprache wie Haskell, sie enthält ebenfalls imperative Elemente, welche die Ausdruckfähigkeit an einigen Stellen vereinfachen sollen. Erste Schritte waren also schnell gemacht. Mit “let” werden Variablen deklariert und definiert, wobei es sich hierbei auch um Funktionen handeln darf. “let twice x = 2*x” erzeugt z.B. eine Funktion “twice”, welche die Signatur “int -> int” besitzt und zu einem übergebenen Argument seinen zweifachen Wert zurückgibt. Diese Funktion darf wieder an weitere Funktionen übergeben werden, Funktionen höherer Ordnung sind also ohne Probleme möglich. F# inferiert dabei den Typ von Variablen, d.h. ihre Signatur wird aus den angegebenen Definitionen automatisch ermittelt und so z.B. auch bei der Fehlerprüfung verwendet. Als Beispiel für eine Signatur sei “List.map” angegeben. Deren Signatur lautet: “val map: (‘a -> ‘b) -> ‘a list -> ‘b list”. What the heck? Eigentlich ist es ganz einfach. “->” gibt jeweils die Abgrenzung zweier Parameter an. Der Ausdruck nach dem letzten “->” stellt den Rückgabetyp dar. Nehmen wir C# als Hilfestellung und schauen uns die Methode “Math.Pow” an, so hat diese in C# die Signatur “double Pow(double x, double y)” und übersetzt auf unser Schema die Signatur “double -> double -> double”. Sie würde also 2 double-Werte als Argumente nehmen und einen double-Wert zurückliefern. Aber zurück zu List.map… (‘a -> ‘b) besagt: “das erste Argument der Funktion List.map ist eine Funktion, welche ein Element des Typs a entgegennimmt und ein Element des Typs b zurückliefert”. Das zweite Argument “‘a list” besagt, dass eine Liste mit Elementen vom Typ a erwartet wird. Der Rückgabetyp von List.map ist ‘b list, was als letzter Term der Signatur ausgewiesen ist. Was macht List.map jetzt eigentlich? Es “mapped” Elemente einer übergebenen Liste mit Hilfe einer ebenfalls als Parameter übergebenen Funktion. Dazu wird auf jedes Listenelement des Typs a die Funktion angewendet, welche ein Element des Typs b zurückliefert. Am Ende ergibt dies eine Liste von Elementen des Typs b, welche zurückgegeben wird. Auch Lambda-Ausdrücke sind in F# kein Problem. “List.map (fun x -> 2*x) numbers” würde z.B. von allen Elementen der Liste “numbers” den doppelten Wert erzeugen und dies als Liste zurückliefern. Klar erkennbar sind bereits hier u.a. das funktionale Paradigma, Typsicherheit und Polymorphismus, auch wird bereits hier die Ausdrucksmächtigkeit erkennbar, wenn man bereit ist sich auf funktionale Programmierung einzulassen…

Quicksort in F#

Beim Stöbern bin ich auf eine F#-Implementierung des Sortieralgorithmus Quicksort gestoßen, welche ich euch nicht vorenthalten wollte:

let lt  x = List.filter (fun xi -> xi < x)
let geq x = List.filter (fun xi -> xi >= x)
 
let rec qs = function
             | []    -> []
             | x::xs -> (xs |> (lt x >> qs)) @ [x] @ (xs |> (geq x >> qs))

That’s it… Über z.B. “printfn “sorted: %A” (qs [3;1;9;5;2;10;8;6;7;4])” kann die Sortierung getestet werden. Zunächst werden zwei Funktionen “lt” und “geq” definiert, welche jeweils eine Element x übergeben bekommen. Sie liefern genau die Funktionen zurück, welche für einen weiteren übergebenen Wert xi berechnen, ob x kleiner oder größer gleich xi ist. “let rec qs …” definiert eine rekursive Funktion qs, welche eine Liste als Argument übergeben bekommt. Mit “|” wird der Wert der Liste geprüft und anhand dessen der Funktionswert bestimmt. Ist die Liste leer (“[ ]”), so wird auch nur eine leere Liste zurückgeliefert. Ansonsten wird die Argumentliste mittels “x::xs” in den Kopf x und die Restliste xs zerlegt und mit diesen beiden Elementen wird der folgende Term definiert. Dieser ist zunächst in 2 Teile aufgeteilt, die mit “@” voneinander getrennt sind. Im mittleren steht mit [x] eine Einerliste, welche nur das Pivotelement des Quicksort-Durchlaufs enthält. Links davon wird die Teilliste von xs erzeugt, welche alle Elemente kleiner als x enthält, rechts davon entsprechend die Teilliste mit allen Elementen größer gleich xs. Mit “(xs |> (lt x >> qs))” werden über den Pipe-Operator |> die Elemente aus xs ausgewählt, die kleiner als x sind (die Liste xs wird mittels Pipe weitergeleitet an lt und qs) und für diese Teilliste wird qs rekursiv aufgerufen (>> stellt die Verkettung zweier Funktionsaufrufe dar). Da mit jedem Aufruf von qs die Liste um mind. 1 Element kleiner wird, terminiert der Algorithmus in endlich vielen Schritten. Ok, an die Syntax muss man sich erst einmal gewöhnen, aber mal ehrlich… wie viele Zeilen hättet ihr in C# gebraucht?

Ja und?

Jetzt könnte man sagen: ja fein, F# ist eine neue funktionale Programmiersprache, hat das .NET Framework unter sich liegen und lässt sich auch recht flexibel verwenden… doch warum in aller Welt sollte mich das kümmern? Funktionale Programmiersprachen gibt es schon seit Ewigkeiten und mit C# komme ich gut zurecht, was will ich mit F#? Die Antwort auf diese Frage ist nicht leicht und zudem recht komplex. Zunächst einmal gibt es derzeit keine sehr guten Gründe, um F# wirklich intensiv zu lernen. Im Arbeitsleben ist diese Sprache noch nicht angelangt und somit eher eine Spielwiese zum Lernen funktionaler Programmierung und zum Erfreuen von enthusiastischen Programmierern. Es ist nicht abzusehen und auch nicht das Ziel von Microsoft, dass F# bestehende Sprachen wie C# ablöst. Ein großer Aspekt für die funktionale Programmierung ist das Problem der parallelen Programmierung. Viele Jahrzehnte lang haben wir sequentiell programmiert und imperative Programmiersprachen eigneten sich hierzu hervorragend. Doch mit dem Aufkommen von Multicore-Prozessoren wird die Notwendigkeit nach der Parallelisierung von Aufgaben immer größer und hier stoßen imperative Programmiersprachen an ihre Grenzen. Funktionale Programmiersprachen hingegen sind zunächst nebenwirkungsfrei und damit grundlegend für eine Parallelisierung geeignet. Variablen sind immutable (unveränderlich), womit Programmteile ohne Probleme verteilt bearbeitet werden können. Funktionale Programmierung kann damit einen Ausweg aus dem Dilemma der Parallelisierung von Programmen weisen. Wichtig dabei ist meiner Meinung nach, dass kein kompletter Paradigmenwechsel vollzogen wird. Funktionale Programmierung ist schwer und teilweise kompliziert, wenn man lange Zeit imperativ programmiert hat. Imperative Programmiersprachen geben einem Programmierer mehr Flexibilität mit dem Nachteil, dass es Wechselwirkungen geben kann, was gerade bei komplexen Softwareanwendungen häufig zu erheblichen Problemen führt. Aber funktionale Elemente werden meiner Meinung nach Einzug in Sprachen, Bibliotheken und Muster halten und somit bestehende Programmiersprachen wie C# bereichern. F# ist dabei auf einem guten Weg, da es eine hohe Ausdrucksmächtigkeit besitzt und performanter agiert als viele seiner funktionalen Kollegen. Erste Elemente von F# sind bereits in C# eingeflossen, es bleibt abzuwarten welche noch folgen werden…

So far for now… Matthias