Сокращение для любой позиции кортежа Нет в F # - PullRequest
0 голосов
/ 16 сентября 2018

Есть ли короткая стрелка для следующего шаблона в F # или я могу без труда создать его, который не зависит от количества элементов кортежа?

 | (None, _, _,_,_) | (_,None,_,_,_) | (_,_,None,_,_) | (_,_,_,None,_) | (_,_,_,_,None)

Идея шаблона была бы *Опция 1004 * для любого элемента, чтобы убедиться, что выполняются только правильные вычисления.

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Если вам действительно нужно иметь дело с опциональными кортежами на регулярной основе, инвертирование логики и использование нескольких вариантов активного паттерна может облегчить боль. Вместо проверки None в любой позиции, проверьте Some во всех положениях.

let (|AllSome5|AnyNone5|) = function
| Some(a), Some(b), Some(c), Some(d), Some(e) -> AllSome5(a, b, c, d, e)
| _ -> AnyNone5
// val ( |AllSome5|AnyNone5| ) :
//   'a option * 'b option * 'c option * 'd option * 'e option ->
//     Choice<('a * 'b * 'c * 'd * 'e),unit>

match Some(42), Some(1.0), Some(0uy), Some("abc"), Some('d') with
| AllSome5(a, b, c, d, e) -> () // do something with 42, 1.0, 0uy, "abc", 'd'
| AnyNone5 -> ()                // otherwise

Достижение независимости от размера кортежа технически не невозможно, но это не красиво. Перегрузка метода в сочетании со статически разрешенными параметрами типа не будет использоваться в качестве активного шаблона, но вместо этого потребуется вызов функции.

let some4 = function
| Some(a), Some(b), Some(c), Some(d) -> Some(a, b, c, d)
| _ -> None
let some5 = function
| Some(a), Some(b), Some(c), Some(d), Some(e) -> Some(a, b, c, d, e)
| _ -> None
type Foo = Foo with
    static member($) (_ : Foo, (a, b, c, d)) = some4(a, b, c, d)
    static member($) (_ : Foo, (a, b, c, d, e)) = some5(a, b, c, d, e)
let inline foo args = Foo $ args

match foo(Some(42), Some(1.0), Some(0uy), Some("abc"), Some('d')) with
| Some(a, b, c, d, e) -> () // do something with 42, 1.0, 0uy, "abc", 'd'
| None -> ()                // otherwise
0 голосов
/ 16 сентября 2018

Если все 5 элементов относятся к одному типу, вы можете использовать предложение when, например:

| (None, _, _,_,_) | (_,None,_,_,_) | (_,_,None,_,_) | (_,_,_,None,_) | (_,_,_,_,None) -> "none!"

Или сделайте вспомогательную функцию, если вам нужно много:

module Tuple5 =
    let toArray (a, b, c, d, e) = [|a; b; c; d; e|]

Конечно, вам нужно будет сделать это для каждого размера кортежа. Вы бы использовали это так:

| x when x |> Tuple5.toArray |> Array.contains None -> ()

Однако мне никогда не требовался набор из 5 элементов в коде F #, где все элементы имеют одинаковый тип. Если это так, рассмотрите возможность использования массива или списка вместо кортежа.

...