F#: арифметический оператор и потеря полиморфизма (ограничение значения?)
Этот код не компилируется:
let f = fun x y -> x <<< y // bit shift
let g = fun x y -> x <<< y
[<EntryPoint>]
let main _ =
printfn "%d" <| f 1 10
printfn "%d" <| f 1L 10 // error
printfn "%d" <| g 1L 10
0
(7,21): error FS0001: This expression was expected to have type
int
but here has type
int64
Я предполагаю, что объединитель исправил параметры типа, связанные с f
а также g
увидев их первые появления. Что управляет этим процессом? Я думаю, что это очень похоже на "ограничение стоимости", но f
а также g
Это уже расширено! Это сложная проблема.
Я бы, конечно, предположил, что за вводом предопределенных операторов со специальным полиморфизмом над целочисленными типами стоит какая-то черная магия, но это только мое предположение. Любая информация приветствуется.
2 ответа
Общее числовое программирование выполняется с использованием статических ограничений членов, которые не могут быть представлены в системе типов.NET. Они существуют только в F# и поэтому должны быть помечены inline
,
Ваш код может быть написан так:
let inline f x y = x <<< y // bit shift
let inline g z y = z <<< y
[<EntryPoint>]
let main _ =
printfn "%d" <| f 1 10
printfn "%d" <| f 1L 10 // works too
printfn "%d" <| g 1L 10
0
Больше информации на MSDN:
Встроенные функции
Статически разрешенные параметры типа
Я думаю, что именно так F# выполняет автоматическое обобщение параметров функции. При первом появлении это означает, что функция 'f' может иметь тип ('a -> 'a -> 'a), но второе появление не соответствует этой сигнатуре, поскольку имеет другую подпись ('b -> 'a -> 'а) потому что он рассматривает int64 и int как разные типы.
Встроенные функции могут иногда решить эту проблему, как упоминал @Daniel
Чуть больше информации можно найти здесь: http://msdn.microsoft.com/en-us/library/dd233183.aspx
Томас Петричек может найти дополнительную информацию об ограничениях статических элементов: http://tomasp.net/blog/fsharp-generic-numeric.aspx/