2
votes

Why doesn't this work?

type RetryBuilder(max) = 
  member x.Return(a) = a               // Enable 'return'
  member x.Delay(f) = f                // Gets wrapped body and returns it (as it is)
                                       // so that the body is passed to 'Run'
  member x.Zero() = failwith "Zero"    // Support if .. then 
  member x.Run(f) =                    // Gets function created by 'Delay'
    let rec loop 0 (Some(ex)) = raise ex
    let rec loop n maybeEx    = try f() with ex -> loop (n-1) (Some(ex))
    loop max None

let retry = RetryBuilder(4)

It says 'incomplete pattern matches on this expression. For example, the value '1' may indicate a case not covered by the pattern'.

But why wouldn't that match the one below? If I remember correctly, Haskell would match that, why doesn't F#?

1

1 Answers

5
votes

You're writing F# code in Haskell syntax. The reason why your code compiles is F# compiler thought there are two loop functions where the former is shadowed by the latter. Obviously in the first loop function, pattern matching fails with any integer different from 0 for the first parameter and None for the second parameter.

A declaration close to Haskell syntax could be:

let rec loop = function 
    | 0, Some ex -> raise ex
    | n, maybeEx -> try f() with ex -> loop (n-1, Some ex)
loop(max, None)