Чтобы подробнее рассказать о том, что сказал Себастьян и о чем пометил 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"
Просто откройте prim-types.fs в вашем дистрибутиве F # и покопайтесь. Вокруг строки 2200 - определения для >>> и других, которые подчеркивают встраивание и другие изящные вещи.