我是 F# 新手。我在闲逛,发现了一些有趣的东西,我希望有人能启发我了解幕后发生的事情。
所以我做了这个功能:let my_func (x, y) = x + y
.
然后我用参数调用该函数1
and 2
给我3
。这是我期望发生的事情,但是当我将两个字符串传递给my_func
尽管我得到了一个错误+
是一个有效的字符串运算符。我重新运行我的代码,但这次只调用my_func
with "cat"
and " dog"
这给了我"cat dog"
。然后我尝试通过1
and 2
回到my_func
才发现my_func
long 不接受整数。
Why is my_func
有这样的行为吗?
let my_func (x, y) = x + y
my_func (1, 2) // produces => 3
my_func ("cat", " dog") // Error
重新运行程序...
let my_func (x, y) = x + y
my_func ("cat", " dog") // produces => "cat dog"
my_func (1, 2) // Error
@MarcinJuraszek 向您展示了如何解决这个问题,但没有提及why它发生了。
你可以这样想:
F# 的类型推断有效从上到下, 左到右- 所以当系统尝试查找类型时my_func
它会发现从您使用该函数的第一行开始分配类型(第一个示例是int
s,第二个是string
s) - 如果您根本不使用它或在 FSharp Interactive 中定义它,它确实会默认为int
.
将函数声明为inline
使 F# 能够使用静态解析类型参数 http://msdn.microsoft.com/en-us/library/dd548046.aspx(由于一些细节,这只能通过inline
函数)然后它确实会做类似的事情鸭子打字从声明中找出该函数需要类型,其中静态+
运算符以某种方式定义。
您可以在函数的类型中看到这一点:
val inline my_func :
x: ^a * y: ^b -> ^c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
这个相当复杂的类型说明了这一点:
必须有静态运算符(+) : ^a * ^b -> ^c
on ^a
(think 'a
)在你写的时候使用+
在函数体内。正如您所看到的,这比您真正需要的更通用,但这不是问题。 F# 将为您应用的此函数的每次出现实现具体版本(用泛型类型替换)(因此在您的示例中将有两个my_func
IL 中的实例化;一个为Int
s 和 1 为String
s) - 但这根本不会在设计时打扰您。
所以你现在拥有了更多generic可以与以下函数一起使用的函数:
-
(+) : Int * Int -> Int
on Int
-
(+) : String * String -> String
on String
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)