我很困惑如何将函数标记为泛型而没有像 ('a -> 'a)
这样的显式类型声明
let add a b = a + b
这给了我们
val add : a:int -> b:int -> int
但是我们可以立即打电话
add "Hello " "World!"
现在add的值是
val add : a:string -> b:string -> string
val it : string = "Hello World!"
如果我们再打电话
add 2 3 // then we get
error: This expression was expected to have type string but here has type int
如何确保函数适用于所有定义函数 (+)
的类型
3 回答
这是F#在壁橱里尴尬的骨架 .
试试这个:
完全通用!显然,函数应用程序和元组工作 .
现在试试这个:
嗯,也是通用的 . 这个怎么样:
啊哈,只要我在那里有一个
(+)
,由于某种原因它变成int
.让我们继续玩:
嗯,有趣 . 事实证明,如果我使函数
inline
,那么F#确实认为它是通用的,但它也给它这个奇怪的when
子句,而我的通用参数有这个奇怪的^
符号而不是通常的勾号 .这个奇怪的语法被称为"statically resolved type parameters"(参见here,有点连贯的解释),基本思想是函数
(+)
要求其参数定义static member (+)
. 我们来验证:现在,问题是CLR不支持这种通用参数(即"any type, as long as it has such and such members"),所以F#必须伪造它并在编译时解析这些调用 . 但正因为如此,使用此功能的任何方法都无法编译为真正的通用IL方法,因此必须是单态的(由
inline
启用) .但是,要求使用算术运算符的每个函数都被声明为
inline
,而不是't it? So F# goes yet another extra step and tries to fix these statically resolved generic parameters based on how they are instantiated later in the code. That'为什么你的函数只要用string
一次变成string->string->string
就会非常不方便 .但是如果你将函数标记为
inline
,则F#将不会将函数编译为IL,因此您的参数保持不变:如果我理解正确,请使用内联:
打印:
链接:http://ideone.com/awsYNI
成为inline