Почему функция F # возвращает подпись "val FunctionName: int -> int"? - PullRequest
1 голос
/ 22 апреля 2009

Я следовал за некоторыми примерами на F # Wikibook о функциях высокого порядка .

Второй фрагмент кода под заголовком, Функция композиции имеет следующий фрагмент кода.

#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....

У меня проблема с пониманием:

let xSquared x = x*x

Когда я запускаю его самостоятельно с помощью интерактивной оболочки F # (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?

Ответы [ 2 ]

11 голосов
/ 22 апреля 2009

Чтобы подробнее рассказать о том, что сказал Себастьян и о чем пометил 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 - определения для >>> и других, которые подчеркивают встраивание и другие изящные вещи.

3 голосов
/ 22 апреля 2009

Имея больше информации, F # может определить, что xSquared вызывается с аргументами с плавающей точкой. Если вы измените negXPlusFive на что-то вроде «let negXPlusFive x = -x + 5», вы обнаружите, что оно, fog и xSquared будет «int -> int».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...