如何编写函数列表?

Avr*_*oel 3 f#

例如,如果我有一个名为 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”不匹配

我究竟做错了什么?

Bru*_*ner 5

看起来面向铁路的编程很适合这里。如果你选择走这条路,你基本上有两个选择。您可以选择全力以赴,也可以采取快速路线。

快捷路线

您重写验证函数以采用 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)

不管怎样,请查看原始文章。还有更多你可以使用的东西:)

编辑:我刚刚注意到我再次写这个答案的速度太慢了。此外,我认为赫尔格对这个概念的解释也比我更好。