Почему моя функция не обобщена интуитивно? - PullRequest
1 голос
/ 20 марта 2012

У меня проблемы с пониманием поведения логического вывода типа F #.Оператор string полагается на статическую диспетчеризацию типа во время компиляции, а не во время выполнения, поэтому что-то вроде let lowerstring = string >> (fun s -> s.ToLowerInvariant()) не обобщается - компилятору необходимо знать тип аргумента.Однако я вижу странное для меня поведение.

Со следующими определениями:

let inline lower (s: string) = s.ToLowerInvariant()

// 'T -> string, constrained to the type of its first use
let lowerstring1 = string >> lower

// Same as above
let lowerstring2 value = value |> string |> lower

// Same as above
let lowerstring3 = box >> string >> lower

// 'a -> string, fully generalized
let lowerstring4 value = value |> box |> string |> lower

Я наблюдаю это поведение:

// val token: JToken
// val num: int

let tokstr1 = lowerstring1 token // lowerstring1 now has type JToken -> string
let numstr1 = lowerstring1 num   // Error, doesn't compile

(* As above with lowerstring2 and lowerstring3 *)

let tokstr4 = lowerstring4 token // lowerstring4 now has type 'a -> string
let numstr4 = lowerstring4 num   // no error, works as 'expected'

I 'Мне непонятно, почему lowerstring3 и lowerstring4 проверяются по-разному.Статические ограничения кажутся вероятными, но если бы это было так, то разве lowerstring4 не удалось бы обобщить?Почему явное присутствие аргумента функции должно иметь значение здесь?

1 Ответ

1 голос
/ 20 марта 2012

F # должен кодировать вплоть до IL, и поскольку в .NET нет универсальных «значений», функции создаются только тогда, когда они являются настоящими синтаксическими функциями (которые генерируются в метод .NET, который может быть универсальным).

(Единственное исключение - [<GeneralizableValueAttribute>], см., Например, здесь .)

...