Function F#泛型/函数重载语法
我对如何在没有像Function F#泛型/函数重载语法,function,generics,types,f#,Function,Generics,Types,F#,我对如何在没有像('a->'a) 这给了我们 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 ex
('a->'a)
这给了我们
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
如何确保函数在定义了函数
(+)
的所有类型上工作如果我理解正确,请使用内联:
let inline add a b = a + b
add 2 3 |> printfn "%A"
add "Hello " "World!" |> printfn "%A"
打印:
5
"Hello World!"
链接:成功
这是F#在衣柜里令人尴尬的骨架
试试这个:
> let mapPair f (x,y) = (f x, f y)
val mapPair : f:('a -> 'b) -> x:'a * y:'a -> 'b * 'b
完全通用!显然,函数应用程序和元组是有效的
现在试试这个:
> let makeList a b = [a;b]
val makeList : a:'a -> b:'a -> 'a list
嗯,也是通用的。这个怎么样:
> let makeList a b = [a + b]
val makeList : a:int -> b:int -> int list
啊哈,只要我在里面有一个(+)
,出于某种原因它就会变成int
。让我们继续玩:
> let inline makeList a b = [a + b]
val inline makeList :
a: ^a -> b: ^b -> ^c list
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
嗯,很有趣。事实证明,如果函数“<代码>内联”,则f yx确实认为它是泛型的,但它在子句时也给出了这个奇怪的<代码>,并且我的通用参数有这个奇怪的代码“^ >代码>符号,而不是通常的嘀嗒声。
这种奇怪的语法被称为“静态解析类型参数”(请参阅,以获得一些连贯的解释),其基本思想是函数(+)
要求其参数定义一个静态成员(+)
。让我们验证一下:
> let x = 0 :> obj
let y = 0 :> obj
let z = x + y
Script1.fsx(14,13): error FS0001: The type 'obj' does not support the operator '+'
> type My() =
static member (+)( a:My, b:My ) = My()
let x = My()
let y = My()
let z = x + y
val x : My
val y : My
val z : My
现在,问题是CLR不支持这种泛型参数(即“任何类型,只要它有这样或那样的成员”),因此F#必须伪造它并在编译时解决这些调用。但正因为如此,任何使用此功能的方法都无法编译为真正的泛型IL方法,因此必须是单态的(由inline
启用)
但是,要求使用算术运算符的每个函数都声明为内联,这将非常不方便,不是吗?因此,F#又多了一步,试图根据这些静态解析的泛型参数在代码后面的实例化方式来修复它们。这就是为什么只要将函数与字符串一起使用一次,它就会变成string->string->string
但是,如果将函数标记为内联,F#就不必修复参数,因为它不必将函数编译为IL,因此参数保持不变:
> let inline add a b = a + b
val inline add :
a: ^a -> b: ^b -> ^c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
“这是F#在衣柜里尴尬的骷髅。”——唯一的一具?我肯定有好几具,但我一点也记不起来了。我想这是一具复制品;如果以前没有人问过,我会非常惊讶。但这是对问题的极好解释。
> let x = 0 :> obj
let y = 0 :> obj
let z = x + y
Script1.fsx(14,13): error FS0001: The type 'obj' does not support the operator '+'
> type My() =
static member (+)( a:My, b:My ) = My()
let x = My()
let y = My()
let z = x + y
val x : My
val y : My
val z : My
> let inline add a b = a + b
val inline add :
a: ^a -> b: ^b -> ^c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)