Получение значений из случая объединения - PullRequest
2 голосов
/ 22 июля 2011

у меня есть что-то вроде

type A = 
   | X of string
   | Y of int

у меня есть последовательность типов X, [X "foo"; X "boo"; X "moo"] есть ли ярлык для создания карты, чтобы преобразовать ее в ["foo"; "boo"; "moo"] без сопоставления?

Спасибо!

Ответы [ 5 ]

4 голосов
/ 22 июля 2011

Я бы вообще не использовал решение, которое не обрабатывает все случаи сопоставления с образцом (например, при использовании fun (X str) -> .... Всегда полезно добавить обработчик, даже если он только что сообщил о более информативной ошибке ( например, случай был неожиданным, потому что он был отфильтрован ранее).

Вы можете расширить решение kvb, используя синтаксис function (который похож на fun с сопоставлением с шаблоном):

List.map (function (X s) -> s | _ -> failwith "Unexpected case")

В качестве альтернативы, если вы хотите игнорировать значения Y (чтобы [X "a"; Y 1; X "b"] становится ["a"; "b"]), вы можете использовать функцию List.choose:

List.choose (function (X s) -> Some s | _ -> None)

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

3 голосов
/ 22 июля 2011

Вы можете использовать это:

List.map (fun (X s) -> s)

Это выполняет совпадение за кулисами, но синтаксис лучше. Вы получите предупреждение, поскольку шаблон является частичным (то есть функция явно не сможет обрабатывать Y _ экземпляров).

3 голосов
/ 22 июля 2011

Только для ухмылки, вы можете сделать это:

let get<'T> = function
  | X s -> box s :?> 'T
  | Y i -> box i :?> 'T

Чтобы получить список X или Y, но не оба.

[X "foo"; X "boo"; X "moo"] |> List.map get<string>
[Y 0; Y 1; Y 2] |> List.map get<int>
[Y 0; X "boo"; Y 2] |> List.map get<int> //oh snap!

Если вы 'все в порядке со значениями в штучной упаковке, это работает для смешанных списков:

let get = function
  | X s -> box s
  | Y i -> box i

[Y 0; X "boo"; Y 2] |> List.map get //no problem

Я предполагаю, что вы заинтересованы в неортодоксальных решениях, поскольку вы спрашиваете, как избежать сопоставления с образцом.; -)

Здесь - еще одно универсальное, но барочное решение.

2 голосов
/ 22 июля 2011

Как и в случае решения @ kvb, вы можете использовать понимание списка с неполным совпадением шаблона:

let xl = [X "foo"; X "boo"; X "moo"]
[for X s in xl -> s]
0 голосов
/ 22 июля 2011

Вы должны соответствовать. Если вы делаете это много, определите функции getX и getY:

let getX (X v) = v

let getY (Y v) = v

Но имейте в виду, что они будут вызывать исключения, если дано значение неправильного регистра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...