3

I found this code in the excellent book F# Design Patterns by Gene Belitski:

let (| `` I'm active pattern `` |) x = x + 2
let (`` I'm active pattern `` y) = 40
(*
val ( |`` I'm active pattern ``| ) : x:int -> int
val y : int = 42
*)

The author recognizes that this is

"a slightly mind boggling example that becomes clear if you remember that the let binding of a value is a corner case of pattern matching based data disassembling, so I'm active pattern gets applied to input argument 40 and binds the result 42 to x."

I don't get it. Why does I'm active pattern gets applied to 40, given that 40 is on the right-hand side? Intuitively I would guess that y = 38, not 42, looking at the expression let (`` I'm active pattern `` y) = 40 as an implicit function.

Can anyone explain?

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
Soldalma
  • 4,636
  • 3
  • 25
  • 38
  • 2
    The example in the OP is a bit contrived but this type of active pattern is often used in convert some input to some output (e.g. string date to DateTime etc.). And because let is pattern matching you get this type of behaviour. This is similar to deconstructing DUs with `let`. E.g. `let (Foo x) = foo` will take out the value wrapped into the Foo DU. – s952163 Feb 09 '17 at 23:50

1 Answers1

7

That's what makes active patterns special; with a normal function the definition let f x = ... mirrors the application of f: you can mentally evaluate f e by substituting e for x in the definition.

By contrast, with an active pattern let (|P|) x = ..., when you see let (P y) = e the fresh identifier y will get the result of applying the body of the definition to e.

This is perhaps easier to see with an active pattern where the result type differs from the input type:

let (|StringValue|) (i:int) = sprintf "%i" i

let (StringValue s) = 1 // s is of type string, with value "1"
kvb
  • 54,864
  • 2
  • 91
  • 133