在F#中,许多采用序列的函数都将序列作为支持流水线操作的最后一个参数. 在设计API时,我可以遵循这种趋势,就像在这个简单的状态机示例中一样: type Transition = { CurrentState : string; Tri
在设计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"
但在某些情况下,序列是不变的,而其他参数则不同.在状态机示例中,对于给定的状态机,转换表(转换)将是固定的.将使用不同的状态和事件多次调用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以支持流水线操作和部分应用程序?
流水线操作使用部分应用程序,它只是通过首先指定参数然后指定函数来调用函数的另一种方法.myTransitions |> getNewState“A”“one”
这里首先部分地应用getNewState来获取具有一个param的函数,然后使用myTransitions调用该函数.
有一个函数可以具有不同的参数顺序但函数名仍然保持相同的方法是使用方法重载,即具有静态方法的类型但随后松开隐式部分应用程序,因为方法将参数作为单个元组.
最好坚持使用一个签名,并且调用者可以根据需要轻松创建另一个具有不同参数顺序的函数.例如,在第二个代码示例中,您可以将第一个示例的getNewState用作:
让stateMachine a b = getNewState a b myTransitions