在 F# 中,许多采用序列的函数都将序列作为支持流水线的最后一个参数。
在设计 API 时,我可以顺应这种趋势,就像在这个简单的状态机示例中一样:
type Transition =
{ CurrentState : string; TriggeringEvent : string; NewState : string }
let getNewState currentState triggeringEvent transitions =
let isMatch t =
t.CurrentState = currentState
&& t.TriggeringEvent = triggeringEvent
match transitions |> Seq.tryFind isMatch with
| Some transition -> Some(transition.NewState)
| None -> None
let myTransitions =
[ { CurrentState = "A"; TriggeringEvent = "one"; NewState = "B" };
{ CurrentState = "B"; TriggeringEvent = "two"; NewState = "A" } ]
let result = myTransitions |> getNewState "A" "one"
printfn "%A" result
这里getNewState
有签名:
(string -> string -> seq<Transition> -> string option)
支持流水线:
myTransitions |> getNewState "A" "one"
但在某些情况下,序列是恒定的,而其他参数则不同。在状态机示例中,transitions
对于给定的状态机,转换表 ( ) 将是固定的。getNewState
将使用不同的状态和事件多次调用。如果序列是第一个参数,调用者可以使用部分应用程序:
let getNewState transitions currentState triggeringEvent =
// body same as before
let stateMachine = getNewState myTransitions
let result1 = stateMachine "A" "one"
let result2 = stateMachine "B" "two"
printfn "%A" result1
printfn "%A" result2
现在getNewState
有签名:
(seq<Transition> -> string -> string -> string option)
并stateMachine
有签名:
(string -> string -> string option)
在调用者的选择下,我如何设计一个 API 来支持流水线和部分应用程序?