I have these types:
type ShouldRetry = ShouldRetry of (RetryCount * LastException -> bool * RetryDelay)
and RetryCount = int
and LastException = exn
and RetryDelay = TimeSpan
type RetryPolicy = RetryPolicy of ShouldRetry
Now I want composability of the retries; something like this:
let serverOverloaded = [| exnRetry<TimeoutException>;
exnRetry<ServerBusyException> |]
|> Array.map (fun fn -> fn (TimeSpan.FromSeconds(4.0)))
let badNetwork = [||] // etc
let compose p1 p2 =
// http://fssnip.net/7h
RetryPolicy(ShouldRetry( (fun (c,e) ->
let RetryPolicy(ShouldRetry(fn)) = p1
let RetryPolicy(ShouldRetry(fn')) = p2
let (cont, delay) = fn c,e
if cont then cont, delay
else
let (cont', delay') = fn' c,e
cont', delay') ))
let finalPolicy = serverOverloaded |> Array.scan compose (RetryPolicies.NoRetry())
But I’m getting compiler errors on fn, delay and fn', saying “The value or constructor ‘fn’ is not defined”.
I can see two problems in your
composefunction.When decomposing
p1andp2, the pattern needs to be wrapped in parentheses (otherwise, the compiler interprets the code as a definition ofRetryPolicyfunction, instead of pattern matching):When calling
fn'a bit later, you need to pass it the arguments in a tuple (otherwise, the compiler thinks that you’re callingfn'with just a single argumentcand then building a tuple):I didn’t check (or tried to run) the whole example, so I don’t know if the rest of the code does what you want.