F# 面向铁路的编程.功能输出不通过

F# 面向铁路的编程.功能输出不通过,f#,F#,我一直在努力,已经到了“将简单函数转换为面向铁路的编程模型”一节,在这一节中,他解释了如何将其他类型的函数拟合到模型中 他举了一个想要清理电子邮件地址的例子(因为我是英国人,所以函数名不同!) 我添加了一些printfn以查看发生了什么。这个函数工作得很好,因为如果我给它传递一个带有大写字母和/或前导/尾随空格的电子邮件的输入,那么输出是一个带有干净的小写电子邮件地址的值 let shouter = { Name = "Jim"; Email = " JIM@SHOUT.com "} clea

我一直在努力,已经到了“将简单函数转换为面向铁路的编程模型”一节,在这一节中,他解释了如何将其他类型的函数拟合到模型中

他举了一个想要清理电子邮件地址的例子(因为我是英国人,所以函数名不同!)

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

let shouter = { Name = "Jim"; Email = "  JIM@SHOUT.com "}
cleanEmail shouter
给出输出

Cleaning email for "Jim"
  email is now "jim@shout.com"
val it : Request = {Name = "Jim";
                    Email = "jim@shout.com";}
但是,如果我将此函数包装在一个开关中,并将其插入验证函数链,则使用原始电子邮件地址。例如,使用这样的验证函数

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
let (>=>) switch1 switch2 input =
  match switch1 input with
  | Success s -> switch2 input
  | Failure f -> Failure f
let validate =
  validateNameNotBlank
  >=> validateNameLength
  >=> switch cleanEmail
  >=> validateEmail
…像这样的接线员

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
let (>=>) switch1 switch2 input =
  match switch1 input with
  | Success s -> switch2 input
  | Failure f -> Failure f
let validate =
  validateNameNotBlank
  >=> validateNameLength
  >=> switch cleanEmail
  >=> validateEmail
…像这样绑在一起

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
let (>=>) switch1 switch2 input =
  match switch1 input with
  | Success s -> switch2 input
  | Failure f -> Failure f
let validate =
  validateNameNotBlank
  >=> validateNameLength
  >=> switch cleanEmail
  >=> validateEmail
…然后当我经过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 ";}
验证“Jim”的名称不为空
正在验证“Jim”的名称长度
为“吉姆”清理电子邮件
电子邮件现在是“jim@shout.com"
正在验证“Jim”的电子邮件(JIM@SHOUT.com )
val it:Result=Success{Name=“Jim”;
电子邮件=”JIM@SHOUT.com ";}
您可以从我输入的printfn中看到cleanEmail函数正在清理电子邮件,但输出显示原始电子邮件被传递到链中的下一个函数


这里我遗漏了什么?

如果你看这篇文章,操作员有定义

let (>=>) switch1 switch2 x = 
    match switch1 x with
    | Success s -> switch2 s
    | Failure f -> Failure f 
当正确转换为变量时:

let (>=>) switch1 switch2 input =
  match switch1 input with
  | Success s -> switch2 s
  | Failure f -> Failure f
实际上,您从未使用
Success
中的
s
,因此相同的输入会一直通过


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

Duh,我真傻!我没有复制和粘贴他的代码,而是自己输入代码(为了让我停下来想一想)。我一定是看错了他的密码,打错了东西。谢谢你的更正和解释。