我在关于高阶函数的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)
我理解问题的是
Run Code Online (Sandbox Code Playgroud)let xSquared x = x*x
当我用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行是>>>和其他显示内联和其他漂亮事物的定义.