Член Enum (флаги) состоит из других членов
[<Flags>]
type LikeMatch =
| None = 0
| Start = 1
| End = 2
| All = Start ||| End //ERROR: Unexpected identifier in union case
Я также пытался квалифицировать участников с типом enum. Есть ли способ сделать это в F#?
3 ответа
Решение
Согласно справочнику по языку F#, сделать это невозможно. Правая часть знака = в перечислении F# должна быть целочисленным литералом
грамматика
type enum-name =
| value1 = integer-literal1
| value2 = integer-literal2
Как говорит JaredPar, это не разрешено языком, но F# имеет двоичные литералы, которые позволяют легко показать, какие биты устанавливаются:
open System
[<Flags>]
type LikeMatch =
| None = 0b000000000
| Start = 0b000000001
| End = 0b000000010
| All = 0b000000011
Мы можем определить комбинации флагов:
- Встроенный - см . ответ Роберта
- В сопутствующем модуле
Каждый вариант имеет свои плюсы и минусы.
1. Встроенные комбинации вручную
[<System.Flags>]
type LikeMatch =
| None = 0b00
| Start = 0b01
| End = 0b10
| All = 0b11 // ❌ Not human-friendly (more difficult to understand it's "Start + End")
let all = LikeMatch.All
// val all: LikeMatch = All
let all' = LikeMatch.Start ||| LikeMatch.End
// val all': LikeMatch = All
// ✔️ Compiler-friendly
2. В сопутствующем модуле
[<System.Flags>]
type Spacing =
| Left = 0b0001
| Right = 0b0010
| Top = 0b0100
| Bottom = 0b1000
[<RequireQualifiedAccess>]
module Spacing =
let Horizontal = Spacing.Left ||| Spacing.Right // ✔️ Human-friendly
let Vertical = Spacing.Top ||| Spacing.Bottom
let All = Horizontal ||| Vertical
let horizontal = Spacing.Horizontal
// val horizontal: Spacing = Left, Right
// ❌ Not "Horizontal"
Также есть разница относительно
HasFlag
, включены комбинации или нет:
[<RequireQualifiedAccess>]
module Enum =
let values<'enum when 'enum :> System.Enum> =
System.Enum.GetValues(typeof<'enum>)
:?> 'enum array
|> Array.toList
let flags<'enum when 'enum :> System.Enum> (enumValue: 'enum) =
values<'enum>
|> List.filter (enumValue.HasFlag)
let flagsInline = Enum.flags LikeMatch.All
// val flagsInline: LikeMatch list = [None; Start; End; All]
// ⚠️ Includes "None" and "All"
let flagsCompanion = Enum.flags Spacing.All
// val flagsCompanion: Spacing list = [Left; Right; Top; Bottom]
// Only includes core flags