Search code examples
f#active-pattern

Why active patterns behave this way?


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?


Solution

  • 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"