Список опций (Ранг * Костюм) в опцию (Ранг * Костюм) - PullRequest
0 голосов
/ 17 июня 2020

Какой был бы наиболее лаконичный способ go из

(Rank * Suit) option list -> (Rank * Suit) list option

Причина в том, что я читаю из командной строки две руки карт "4S 4H 4D 4C AS; JS KD QC 10H 2C", поэтому я разбираю каждую часть рука, затем верните полную руку, которая, очевидно, может потерпеть неудачу. *

Если они все - Some (из варианта (Ранг * Костюм)), тогда он вернет Some (из (Rank * Suit) list)

Итак, я получил

type Rank = One | Two | Three
type Suit = Spades | Hearts

type Card = Rank * Suit

[ Some (One, Spades); Some (Two, Hearts); None ] 
  |> List.map (fun card -> Option.map (fun actualCard -> ) ) 

И мой мозг как бы растаял ... Мне кажется, что мне нужен какой-то метод Option.collect ... или Option.reduce что-то ...


Edit

Это последнее утверждение заставило меня задуматься:

  cards
  |> Seq.map parseCard
  |> Seq.fold (fun agg elem -> 
                  match agg with
                  | Some l -> 
                      match elem with
                      | Some card -> Some ( l @ [ card ] )
                      | None -> None
                  | None -> None ) (Some [])

Должен быть более лаконичный способ?


Edit 2

это оно?

cards
  |> Seq.map parseCard
  |> Seq.fold (fun agg elem -> 
                  agg |> Option.bind ( fun l -> 
                    elem |> Option.map ( fun card ->
                      l @ [ card ]
                    )
                  )) (Some [])

Ответы [ 2 ]

3 голосов
/ 18 июня 2020

А что насчет чего-то супер простого и легкого для понимания:

let parseHand cards =
    let maybeCards = cards |> List.map parseCard
    if maybeCards |> List.contains None
    then None
    else Some (maybeCards |> List.choose id)
3 голосов
/ 17 июня 2020

Функция, которую вы ищете, обычно называется sequence и является частью более общей c абстракции, называемой Traversable .

Для списков и параметров вы можете закодировать ее вот так:

let sequence t = List.foldBack (Option.map2 (fun x y -> x::y)) t (Some [])

использование

sequence [ Some (One, Spades); Some (Two, Hearts) ]
// val it : (Rank * Suit) list option = Some [(One, Spades); (Two, Hearts)]

sequence [ Some (One, Spades); Some (Two, Hearts); None ]
// val it : (Rank * Suit) list option = None
...