現在想象一下,我想這樣一種類型, 只接受(北,南) 或(東,西)的元組。
有趣的功能請求:聽起來像你想要的「靜態範圍約束」,例如,
//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)]