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

dan*_*die 1 f# monomorphism

我在关于高阶函数的F#Wikibook上关注了一些例子.

标题下的第二个代码片段,Composition Function具有以下代码片段.

#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....
Run Code Online (Sandbox Code Playgroud)

我理解问题的是

let xSquared x = x*x
Run Code Online (Sandbox Code Playgroud)

当我用F#interactive shell(fsi.exe)单独运行它时,我得到以下签名.

> let xSquared x = x*x;;

val xSquared : int -> int
Run Code Online (Sandbox Code Playgroud)

但是当我运行整个代码片段时,xSquared返回以下内容.

val compose : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
val xSquared : float -> float
val negXPlusFive : float -> float
val fog : (float -> float)
Run Code Online (Sandbox Code Playgroud)

为什么xSquared需要float和回报float

Mic*_*lGG 11

为了扩展塞巴斯蒂安所说的以及jleedev标记的内容,可以使用以下函数:

let xSquared x = x*x
Run Code Online (Sandbox Code Playgroud)

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

但是,F#支持内联,它允许函数更通用,因为它们被内联到每个调用点.这允许你有一个像浮点数,整数等一样的xSquared函数,任何带*运算符的类型.

> let inline xSquared x = x*x;;

val inline xSquared :
   ^a ->  ^b when  ^a : (static member ( * ) :  ^a *  ^a ->  ^b)
Run Code Online (Sandbox Code Playgroud)

现在注意函数类型是如何^ 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"
Run Code Online (Sandbox Code Playgroud)

只需在你的F#发行版中打开prim-types.fs并四处寻找.第2200行是>>>和其他显示内联和其他漂亮事物的定义.