2012-02-22 3 views
1

У меня есть эти типы:F шаблон # Compose соответствует функции

type ShouldRetry = ShouldRetry of (RetryCount * LastException -> bool * RetryDelay) 
    and RetryCount = int 
    and LastException = exn 
    and RetryDelay = TimeSpan 

    type RetryPolicy = RetryPolicy of ShouldRetry 

Теперь я хочу компонуемости из повторных попыток; что-то вроде этого:

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()) 

Но я получаю ошибки компилятора на fn, delay и fn', говоря: «Значение или конструктора„п“не определен».

ответ

3

Я вижу две проблемы в вашей функции compose.

При разложении p1 и p2, образец должен быть заключен в скобки (в противном случае, компилятор интерпретирует код как определение RetryPolicyфункции вместо сопоставления с образцом):

let (RetryPolicy(ShouldRetry(fn))) = p1 
let (RetryPolicy(ShouldRetry(fn'))) = p2 

При вызове fn' немного позже, вам нужно передать ему аргументы в кортеже (в противном случае компилятор думает, что вы вызываете fn' только с одним аргументом c, а затем строя кортеж):

let (cont', delay') = fn' (c,e) 

Я не проверял (или пытался запустить) весь пример, поэтому я не знаю, делает ли остальная часть кода то, что вы хотите.

Смежные вопросы