F#, Chain Of Responsibility, And High Ordered Functions

I was working though Tao Liu’s F# for C#  Developers book

image

when I got to the chapter on F# and Design Patterns.  This is a great chapter.    Typically F# books introduce the language from the language on out.  This chapter takes a different approach – it shows the language in action using commonly accepted design patterns.  I was working through the section on the Chain Of Responsibility pattern when I got to this code snippet

  1. let check f (record,result) =
  2.     if not result then record, false
  3.     else record, f(record)

 

Looking at the code, I get that we are assigning a function called check that has a tuple with record called ‘record” and a Boolean called ‘result’.  However, what is that ‘f’?  Basically, what the F is that f in F#?  Looking at the REPL results, I see that it was this signature:

image

Basically, f is a function called ‘f’ that I am passing in.  I am then invoking this function here:

  1. let chainOfResponsibility = check validAge >> check validHeight >> check validWeight
  2.  
  3. let test1 = {Name="Test"; Age=45; Weight=175.; Height=175.}
  4.  
  5. printfn "test result = %A" (chainOfResponsibility (test1, true) |> snd)

 

So this is an example, I think, of two language constructs.  The first is high ordered functions – where check takes in a function as a parameter.  Next, this is an example of currying – where chainOfResponsibility only passes in the function, not the tuple.  I think.

To further research this, I looked up Chain of Responsibility on Wikipedia and took a look at the C# example.  To do it the C# way, created 6 files

image

with each file having the implementation found on the Wikipedia article.  The Logger class defines the behavior:

  1. public abstract class Logger
  2. {
  3.     protected LogLevel logMask;
  4.     protected Logger next;
  5.  
  6.     public Logger(LogLevel mask)
  7.     {
  8.         this.logMask = mask;
  9.     }
  10.  
  11.     public Logger SetNext(Logger nextlogger)
  12.     {
  13.         next = nextlogger;
  14.         return nextlogger;
  15.     }
  16.  
  17.     public void Message(string msg, LogLevel severity)
  18.     {
  19.         if ((severity & logMask) != 0)
  20.         {
  21.             WriteMessage(msg);
  22.         }
  23.         if (next != null)
  24.         {
  25.             next.Message(msg, severity);
  26.         }
  27.     }
  28.  
  29.     abstract public void WriteMessage(string msg);
  30.  
  31. }

 

and the individual implementations in the classes:

  1. public class FileLogger : Logger
  2. {
  3.     public FileLogger(LogLevel mask)
  4.         : base(mask)
  5.     { }
  6.  
  7.     public override void WriteMessage(string msg)
  8.     {
  9.         //Placeholder for File writing logic
  10.         Debug.WriteLine("Writing to Log File: " + msg);
  11.     }
  12. }

What is interesting to me is the Logger.SetNext() method is used to move to the next implementation in the chain.  I then set to write the example in FSharp using Liu’s template.  I did this:

  1. type Logger() =
  2.     let LogToConsole logLevel =
  3.         //Implementation
  4.         true
  5.  
  6.     let LogToEmail logLevel =
  7.         //Implementation
  8.         true
  9.  
  10.     let LogToFile logLevel =
  11.         //Implementation
  12.         true
  13.  
  14.     let check f (logLevel, result) =
  15.         if not result then logLevel, false
  16.         else logLevel, f(logLevel)
  17.  
  18.     let chainOfResponsibility =
  19.         check LogToConsole >> check LogToEmail >> check LogToFile
  20.  
  21.     let mutable logLevel = LogLevel.None
  22.     member this.CurrentLogLevel with get() = logLevel
  23.                                 and set(v) = logLevel <- v
  24.  
  25.     member this.WriteMessage () =
  26.         chainOfResponsibility (logLevel,true) |> snd

So there are a couple of observations.

1) F# is more terse – and more readable

2) Instead of creating a MoveNext function, the chainOfResponsibility uses the >> operator to move to the next.

3) These 2 code bases are not functionally equivalent – I have to keep working on the F# one.

4) How much fun is F#?

 

One Response to F#, Chain Of Responsibility, And High Ordered Functions

  1. Pingback: F# Weekly #47, 2013 | Sergey Tihon's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: