为什么 F# 函数返回“val FunctionName: int -> >”的签名 整数”?

发布于 2024-07-17 19:35:50 字数 983 浏览 6 评论 0原文

我正在关注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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苏大泽ㄣ 2024-07-24 19:35:50

为了扩展 Sebastian 所说的和 jleedev 标记的内容,可以使用如下函数:

let xSquared x = x*x

只能在具有运算符 * 的类型上工作。 默认情况下, int 在这些情况下获胜。 它不可能是真正通用的,因为 .NET 没有办法表示“任何具有 * 的类型”约束。

然而,F# 支持内联,这使得函数更加通用,因为它们被内联到每个调用点中。 这允许您拥有像 xSquared 这样的函数,可以处理浮点数、整数等——任何带有 * 运算符的类型。

> let inline xSquared x = x*x;;

val inline xSquared :
   ^a ->  ^b when  ^a : (static member ( * ) :  ^a *  ^a ->  ^b)

现在注意函数类型是 ^a ->; ^b. 这类似于 'a ->; 'b,但类型变量必须静态解析。 由于 F# 没有类型类,因此这就是操作符的处理方式。

实际上,您可以使用它自己的 * 成员来定义您自己的类型来执行您想要的任何操作,并且它可以与 xSquared 一起使用:

type Foo(x) =
    member this.Y = x - 1
    static member (*) (x:Foo, y:Foo) = string <| x.Y * y.Y + 1

let a = Foo(10);;

type Foo =
  class
    new : x:int -> Foo
    member Y : int
    static member ( * ) : x:Foo * y:Foo -> string
  end
val a : Foo

> xSquared a;;
val it : string = "82"

只需在 F# 发行版中打开 prim-types.fs 并四处查看。 2200行左右是>>的定义。 以及其他展示内联和其他漂亮东西的人。

To expand on what Sebastian said and what jleedev tagged, a function like:

let xSquared x = x*x

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.

> let inline xSquared x = x*x;;

val inline xSquared :
   ^a ->  ^b when  ^a : (static member ( * ) :  ^a *  ^a ->  ^b)

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:

type Foo(x) =
    member this.Y = x - 1
    static member (*) (x:Foo, y:Foo) = string <| x.Y * y.Y + 1

let a = Foo(10);;

type Foo =
  class
    new : x:int -> Foo
    member Y : int
    static member ( * ) : x:Foo * y:Foo -> string
  end
val a : Foo

> xSquared a;;
val it : string = "82"

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.

倾听心声的旋律 2024-07-24 19:35:50

有了更多信息,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".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文