gpt4 book ai didi

f# - 为什么函数绑定(bind)到它们传递的第一种类型

转载 作者:行者123 更新时间:2023-12-04 17:18:49 25 4
gpt4 key购买 nike

我是 F# 的新手。我在乱搞,发现了一些有趣的东西,我希望有人能启发我了解幕后发生的事情。

所以我做了这个函数:let my_func (x, y) = x + y .

然后我用 args 1 调用函数和 2给我3 .这是我期望发生的,但是当我将两个字符串传递给 my_func 时即使 + 出现错误是带字符串的有效运算符。我重新运行了我的代码,但这次只调用 my_func"cat"" dog"这给了我"cat dog" .然后我尝试通过 12返回 my_func才发现my_func no long 接受整数。

为什么是 my_func表现得这样?
let my_func (x, y) = x + ymy_func (1, 2) // produces => 3my_func ("cat", " dog") // Error
重新运行程序 ...
let my_func (x, y) = x + ymy_func ("cat", " dog") // produces => "cat dog"my_func (1, 2) // Error

最佳答案

@MarcinJuraszek 向您展示了如何解决此问题,但没有说明为什么会发生。

你可以这样想:

F# 的类型推断从上到下、从左到右运行 - 所以当系统尝试查找 my_func 的类型时它会从您使用该函数的第一行中找到分配类型(第一个示例是 int s,第二个示例是 string s) - 如果您根本不使用它或在 FSharp Interactive 中定义它它确实会默认为 int .

将函数声明为 inline使 F# 能够使用 statically resolved type parameters (由于某些细节,这仅适用于 inline 函数)然后它确实会执行类似鸭子类型的操作,以从声明中找出函数需要静态 + 的类型运算符以某种方式定义。

您可以在函数的类型中看到这一点:

val inline my_func :
x: ^a * y: ^b -> ^c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)

这个相当复杂的类型就是这样说的:

必须有静态运算符 (+) : ^a * ^b -> ^c^a (想想 'a )当你写 + 时使用在函数体内。如您所见,这比您真正需要的更通用,但这不是问题。 F# 将为您应用的此函数的任何出现实现具体版本(替换通用类型)(因此在您的示例中,您的 IL 中将有两个 my_func 实例化;一个用于 Int s,一个用于 String s ) - 但这在设计时根本不会打扰您。

所以你现在有了一个更通用的函数,可以用于:
  • (+) : Int * Int -> IntInt
  • (+) : String * String -> StringString
  • 关于f# - 为什么函数绑定(bind)到它们传递的第一种类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26667810/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com