为什么 F# 函数返回“val FunctionName: int -> >”的签名 整数”?
我正在关注F# Wikibook on High Order Functions 上的一些示例。
标题下的第二个代码片段,组合函数具有以下代码片段。
#light
open System
let compose f g x = f (g x)
let xSquared x = x*x
let negXPlusFive x = -x/2.0 + 5.0
let fog = compose xSquared negXPlusFive
// ... Console.WriteLine statements....
我理解上遇到的问题是
令 xSquared x = x*x
当我使用 F# 交互式 shell (fsi.exe) 单独运行它时,我得到以下签名。
> let xSquared x = x*x;;
val xSquared : int -> int
但是当我运行整个代码片段时,xSquared
返回以下内容。
val compose : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
val xSquared : float -> float
val negXPlusFive : float -> float
val fog : (float -> float)
为什么xSquared
采用float
并返回float
?
I was following some examples on F# Wikibook on High Order Functions.
Second code snippet under title, Composition Function has following code snippet.
#light
open System
let compose f g x = f (g x)
let xSquared x = x*x
let negXPlusFive x = -x/2.0 + 5.0
let fog = compose xSquared negXPlusFive
// ... Console.WriteLine statements....
The one I am having problem understanding is
let xSquared x = x*x
When I run it with F# interactive shell (fsi.exe) by itself, I get the following signature.
> let xSquared x = x*x;;
val xSquared : int -> int
But when I run the whole code snippet, xSquared
returns the following.
val compose : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
val xSquared : float -> float
val negXPlusFive : float -> float
val fog : (float -> float)
Why does xSquared
takes float
and returns float
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为了扩展 Sebastian 所说的和 jleedev 标记的内容,可以使用如下函数:
只能在具有运算符 * 的类型上工作。 默认情况下, int 在这些情况下获胜。 它不可能是真正通用的,因为 .NET 没有办法表示“任何具有 * 的类型”约束。
然而,F# 支持内联,这使得函数更加通用,因为它们被内联到每个调用点中。 这允许您拥有像 xSquared 这样的函数,可以处理浮点数、整数等——任何带有 * 运算符的类型。
现在注意函数类型是 ^a ->; ^b. 这类似于 'a ->; 'b,但类型变量必须静态解析。 由于 F# 没有类型类,因此这就是操作符的处理方式。
实际上,您可以使用它自己的 * 成员来定义您自己的类型来执行您想要的任何操作,并且它可以与 xSquared 一起使用:
只需在 F# 发行版中打开 prim-types.fs 并四处查看。 2200行左右是>>的定义。 以及其他展示内联和其他漂亮东西的人。
To expand on what Sebastian said and what jleedev tagged, a function like:
Can only work on a type that has an operator *. By default, int wins in these situations. It cannot be truly generic because .NET doesn't have a way of representing the constraint "any type that has *".
However, F# supports inlining, which allows functions to be more generic, because they are inlined into each callsite. This allows you to have a function like xSquared that works on floats, ints, etc., -- any type with a * operator.
Now notice how the function type is ^a -> ^b. This is similar to 'a -> 'b, except the type variables must be statically resolved. Because F# doesn't have typeclasses, this is how operators are handled.
You can actually define your own type with it's own * member to do whatever you desire, and it'd work with xSquared:
Just open prim-types.fs in your F# distro and poke around. Around line 2200 are the definitions for >>> and others which show off inlining and other nifty things.
有了更多信息,F# 就可以确定 xSquared 是使用浮点参数调用的。 如果将 negXPlusFive 更改为“let negXPlusFive x = -x + 5”之类的内容,您会发现,fog 和 xSquared 将是“int -> int”。
With more information, F# can determine that xSquared is called with float arguments. If you change negXPlusFive to something like "let negXPlusFive x = -x + 5" you would find that it, fog and xSquared would be "int -> int".