Как сопоставить шаблон в конструкторах объединения в `for.. in`
В Haskell, если у меня есть список типизированных типов объединения, например:
example :: [Either Int Char]
example = [Left 3, Right 'b', Left 6, Left 9, Right 'c']
Я могу использовать небольшой "трюк", чтобы извлечь все результаты, соответствующие определенному шаблону:
lefts :: [Int]
lefts = [l | Left l <- example]
Однако, если я попытаюсь перевести это на F #, я получаю сообщение об ошибке:
let lefts = [for Choice1Of2 l in example -> l]
~~~~~~~~~~~~
Incomplete pattern matches on this expression. (...)
Это имеет большое значение (это может быть даже лучше, чем молча игнорирование значений Right
, таких как Haskell!), но в F # есть ли удобный способ извлечения (и совпадения) всех значений сопоставление определенного шаблона в списке/последовательности?
Ответы
Ответ 1
В F #, если вы не соответствуете всем случаям, вы получите предупреждение во всех сценариях.
Итак, вы можете написать совпадение с обоими случаями внутри выражения, но для вашего примера, а не для понимания, я бы использовал функцию List.choose
:
let example = [Choice2Of2 3; Choice1Of2 'b'; Choice2Of2 6; Choice2Of2 9; Choice1Of2 'c']
List.choose (function (Choice1Of2 x) -> Some x | _ -> None) example
// val it : char list = ['b'; 'c']
Эта функция удобна для этих случаев.
Ответ 2
Я думаю, что самая близкая вещь, которую вы можете использовать, используя выражения списка F #, выглядит примерно так:
let lefts example =
[ for e in example do
match e with Choice1Of2 l -> yield l | _ -> () ]
Если я правильно понимаю код Haskell, часть после |
используется не только как экстрактор, но и как фильтр - неявно пропускает все вещи, которые не соответствуют шаблону.
F # не имеет такого же понятия в выражениях списков, поэтому вам нужно быть более подробным. Здесь мы просто перебираем все элементы с помощью for
, а затем явно используем yield
для создания нового значения для каждого Choice1Of2
в исходном списке (и мы просто пропускаем что-либо еще).
В зависимости от того, что вы делаете, использование List.choose
(как упоминалось в ответе Густаво) может быть проще. Но выше, вероятно, ближе всего к синтаксису понимания Haskell.