F#两种不同类型的函数参数

没有

我正在尝试制作一个将字符串和整数作为参数/输入的函数。

let rec twoTwo (s : string) (n : int) = 
  match n with 
  |0 -> 0 
  |_ -> s + (twoTwo s (n-1))

printfn "%A" (twoTwo "string" 5)

在这里,我得到一个错误,即类型为int与类型字符串不匹配。超越我为什么?它是在递归调用中错误键入不匹配的。

怎么了?

费奥多·索金(Fyodor Soikin)

这是一个要考虑的问题:函数返回什么?

如果查看的第一个分支,则match返回int,但是在第二个分支中,您将自己的返回值与一起使用string,因此返回值必须为字符串。

那是什么呢?编译器无法分辨您的意思,因此抱怨。

回应您的评论:
编译器首先在第一个分支中读取零,然后在此基础上确定函数的返回必须为int之后,编译器遇到了字符串连接,发现已经确定的返回类型不合适,并发出了错误。
如果分支反向,则逻辑也将反向:编译器将首先遇到串联,并在此基础上确定返回类型必须为string在那之后,它将遇到零,看到它与先前确定的返回类型不匹配,并抱怨。在这种情况下,错误将为零。
在这种情况下,您会抱怨吗?为什么?您如何期望编译器知道错误为零,而不是串联?编译器可能只知道两个分支不匹配。它不知道哪个是正确的。

认为这很明显,因为您知道自己打算做什么。但是编译器不知道您打算做什么,它只能看到您编写的内容。

用另一种语言,您可以称其为“新手友好的”,例如C#(或Java),这种情况不会出现,因为您总是被迫明确地指定所有返回和参数类型。这使错误更容易理解,因为现在编译器可以告诉哪个分支是错误的:它与显式声明的返回类型不一致。
但是,如果您考虑一下,您只是将问题移到了上游:编译器如何知道显式声明的类型是正确的?编译器只是假设声明的类型是最终真理,但这仅是一个约定。是的,您很熟悉-但是就像按顺序阅读程序一样随意。

但是,如果您发现此方法更简单,则也可以在F#中完全使用它。F#在C#可以(然后是某些地方)的所有地方都允许(尽管不需要)显式类型规范:

let rec twoTwo (s : string) (n : int) : string = 
  match n with 
  |0 -> 0   // Error on this line: this expression was expected to have type string, but here has type int
  |_ -> s + (twoTwo s (n-1))

实际上,添加显式类型规范是一种常见的调试技术。当我发现自己的类型不匹配错误不是很明显时,我开始向事情添加类型规范,直到该错误成为焦点。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章