例如,如果我有一个名为 Person 的类型和函数列表......
let checks = [checkAge; checkWeight; checkHeight]
Run Code Online (Sandbox Code Playgroud)
...其中每个函数的类型都是 (Person -> bool),我想做相当于...
checkAge >> checkWeight >> checkHeight
Run Code Online (Sandbox Code Playgroud)
...但是我事先不知道列表中有哪些功能,我该怎么做?
我尝试了以下...
checks |> List.reduce (>>)
Run Code Online (Sandbox Code Playgroud)
...但这给出了以下错误...
错误 FS0001:类型不匹配。期待 (Person -> bool) -> (Person -> bool) -> Person -> bool
但给定一个
(人 -> 布尔) -> (布尔 -> 'a) -> 人 -> 'a
类型“Person”与类型“bool”不匹配
我究竟做错了什么?
看起来面向铁路的编程很适合这里。如果你选择走这条路,你基本上有两个选择。您可以选择全力以赴,也可以采取快速路线。
快捷路线
您重写验证函数以采用 aPerson option而不是简单的Person.
let validAge (record:Record option) =
match record with
| Some rec when rec.Age < 65 && rec.Age > 18 -> record
| None -> None
Run Code Online (Sandbox Code Playgroud)
现在您应该能够轻松链接您的函数。
checks |> List.reduce (>>)
Run Code Online (Sandbox Code Playgroud)
全部投入
或者,如果您很懒并且不想在每个验证函数中匹配 .. ,您可以编写更多代码。(样本取自[ 1 ])
首先需要进行一些设置。我们将定义一个特殊的返回类型,以便我们可以获得有意义的错误消息。
type Result<'TSuccess,'TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure
Run Code Online (Sandbox Code Playgroud)
绑定函数,将验证绑定在一起
let bind switchFunction =
function
| Success s -> switchFunction s
| Failure f -> Failure f
Run Code Online (Sandbox Code Playgroud)
您还必须重写您的验证函数。
let validAge (record:Record) =
if record.Age < 65 && record.Age > 18 then Success input
else Failure "Not the right age bracket"
Run Code Online (Sandbox Code Playgroud)
现在结合
checks |> List.reduce (fun acc elem -> acc >> bind elem)
Run Code Online (Sandbox Code Playgroud)
不管怎样,请查看原始文章。还有更多你可以使用的东西:)
编辑:我刚刚注意到我再次写这个答案的速度太慢了。此外,我认为赫尔格对这个概念的解释也比我更好。