铁路导向编程 - 功能输出不通过

Avr*_*oel 3 f#

我一直在研究ROP上的这篇文章,并已经达到了" 将简单函数转换为面向铁路的编程模型 "这一部分,他解释了如何将其他类型的函数融入模型中.

他给出了一个想要清理电子邮件地址的例子(功能名称不同,因为我是英国人!)......

let cleanEmail person =
  printfn "Cleaning email for \"%s\"" person.Name
  let newPerson = { person with Email = person.Email.Trim().ToLower() }
  printfn "  email is now \"%s\"" newPerson.Email
  newPerson
Run Code Online (Sandbox Code Playgroud)

我添加了一些printfn来查看发生了什么.这个函数工作正常,因为如果我传递一个带有大写字母和/或前导/尾随空格的电子邮件的输入,则输出是一个带有干净的小写电子邮件地址的值...

let shouter = { Name = "Jim"; Email = "  JIM@SHOUT.com "}
cleanEmail shouter
Run Code Online (Sandbox Code Playgroud)

给出输出......

Cleaning email for "Jim"
  email is now "jim@shout.com"
val it : Request = {Name = "Jim";
                    Email = "jim@shout.com";}
Run Code Online (Sandbox Code Playgroud)

但是,如果我将此函数包装在交换机中,并将其插入验证函数链中,则使用原始电子邮件地址.例如,使用这样的验证功能......

let validateNameNotBlank person =
  printfn "Validating name not blank for \"%s\"" person.Name
  if person.Name = "" then Failure "Name must not be blank"
  else Success person
Run Code Online (Sandbox Code Playgroud)

......像这样的运营商......

let (>=>) switch1 switch2 input =
  match switch1 input with
  | Success s -> switch2 input
  | Failure f -> Failure f
Run Code Online (Sandbox Code Playgroud)

......像这样绑在一起......

let validate =
  validateNameNotBlank
  >=> validateNameLength
  >=> switch cleanEmail
  >=> validateEmail
Run Code Online (Sandbox Code Playgroud)

...然后当我通过shouter时,我得到了以下内容......

Validating name not blank for "Jim"
Validating name length for "Jim"
Cleaning email for "Jim"
  email is now "jim@shout.com"
Validating email for "Jim" (  JIM@SHOUT.com )
val it : Result<Request,string> = Success {Name = "Jim";
                                       Email = "  JIM@SHOUT.com ";}
Run Code Online (Sandbox Code Playgroud)

您可以从我输入的printfn中看到cleanEmail函数正在清理电子邮件,但输出显示原始电子邮件被传递到链中的下一个函数.

我错过了什么?

Joh*_*mer 5

如果你看一下这篇文章,那么运营商就有了这个定义

let (>=>) switch1 switch2 x = 
    match switch1 x with
    | Success s -> switch2 s
    | Failure f -> Failure f 
Run Code Online (Sandbox Code Playgroud)

在正确翻译成您的变量时,它是:

let (>=>) switch1 switch2 input =
  match switch1 input with
  | Success s -> switch2 s
  | Failure f -> Failure f
Run Code Online (Sandbox Code Playgroud)

你从来没有真正使用过s,Success所以相同的输入只是不断传递.

仔细检查一下>=>这种问题就会发现这个问题,因为你们应该给出相同类型的问题,switch1以及switch2它们何时应该有不同的类型.