现在想象一下,我想这样一种类型, 只接受(北,南) 或(东,西)的元组。
有趣的功能请求:听起来像你想要的“静态范围约束”,例如,
//fictional syntax for static range constraints
type TrainLine = (a,b) where (a=North and b=South) or (a=East and b=West)
let northSouth = TrainLine(North,South) // compiles
let northEast = TrainLine(North,East) // does not compile
这种特征似乎只有文字语言合理的,但如果我们陷入麻烦的是,当我们只考虑在运行时已知值:
let parseDirection userInputString =
match userInputString with
| "North" -> North
| "South" -> South
| "East" -> East
| "West" -> West
| _ -> failwith "invalid direction"
let directionA = parseDirection(System.Console.ReadLine())
let directionB = parseDirection(System.Console.ReadLine())
//compiler can't enforce constraint because direction values unknown until runtime
let trainLine = TrainLine(directionA,directionB)
然而,F#的确实有一个很好的集在活动模式功能,它可以帮助运行时输入转换成一组已知的情况下,然后用静态的坚定信心:
let (|NorthSouth|EastWest|Invalid|) (a,b) =
match a,b with
| North,South -> NorthSouth
| East,West -> EastWest
| _ -> Invalid
let trainLines = [(North,South); (South,North); (East,West); (North,East);(North,North); (South,East)]
let isValidTrainLine trainLine =
match trainLine with
| NorthSouth -> true
| EastWest -> true
| Invalid -> false
let validTrainLines = trainLines |> List.filter isValidTrainLine
//val it : (Direction * Direction) list = [(North, South); (East, West)]