#generics #f#
#универсальные #f#
Вопрос:
Следующий код имеет подпись 'c -> 'c
:
let f (x: 'c) = x
Однако следующий код имеет подпись obj -> obj
:
let f<'a> (x: 'c) = x
Добавление 'c
параметра type исправляет сигнатуру, возвращая ее к 'c -> 'c
:
let f<'a, 'c> (x: 'c) = x
Возможно ли явно объявить только некоторые из подписей? Я в основном хочу что-то вроде
let f<'a> (x: MyType<'c>) =
let foo = doSomethingBasedOn typeof<'a>
processXWithoutCaringAboutTypeC x foo
Это что-то вроде десериализации или распаковки, поэтому мне нужны явные аргументы типа для 'a
, но меня действительно не волнует тип 'c
и я предпочел бы не указывать его явно (или подстановочный тип).
Комментарии:
1. Я предполагаю, что проблема в том, что в вашем последнем примере
processXWithoutCaringAboutTypeC
нужно будет знать о типе'c
, ожидая его в качестве аргумента типа (который обычно выводится компилятором). Я сомневаюсь, что вы можете сделать что-то лучше, чемlet f<'a> (x : MyType<_>) = ...
2. Вы уверены, что это не ограничивает ‘c значением obj? (Не перед компьютером прямо сейчас)
3. Что вы подразумеваете под «этим»?
4.
let f<'a> (x : MyType<_>) = ...
. Только что протестированный сейчас, он действительно ограничиваетx
доMyType<obj>
.5. В таком случае, я подозреваю, что ваша функция
processXWithoutCaringAboutTypeC
вообще не принимает параметр типа. Можете ли вы показать его подпись?
Ответ №1:
Чтобы прямо ответить на ваш вопрос, нет способа включить только подмножество общих параметров в явный список общих параметров ( <'a,'b,...>
), ни при определении, ни при использовании функции. Но из вашего описания не ясно, что это действительно важно для вашего варианта использования.
-
То, что вы явно используете аргументы универсального типа в определении функции, не означает, что вам также нужно делать это при вызове функции:
let f<'a,'c> (x: 'c) = x f 1 # works fine with type inference
-
Если возвращаемый тип
f
includes'a
каким-либо образом в вашем втором случае, то вывод типа, вероятно, также позволит вам пропустить явные параметры типа даже в определенииf
.
Однако, если 'a
нигде не отображается в сигнатуре f
(как часть ввода или вывода) и это существенным образом влияет на поведение, тогда его нужно будет указать явно как аргумент типа при вызове f
, потому что вывод типа F # не может определить, каким он должен быть, что заставит вас указать и другие аргументы типа (хотя, возможно, в качестве подстановочных знаков).
Комментарии:
1. Спасибо. К сожалению для меня, случай действительно является вашим пунктом № 2.
MyType<_>
содержит элементы типаSystem.Type
и'a
используется для сравнения с этим типом. Параметр type toMyType<_>
не имеет отношения к данному конкретному сравнению. Поэтому я должен указать'a
явно при вызове.2. В этом случае вместо использования универсального параметра
'a
вы можете просто получить параметрta
типаSystem.Type
и выполнить сравнение, которое вам нужно с ним выполнить. Если вы передаетеta
в качестве первого параметра, то вы можете даже использовать частичное применение.3. Да, фактически, я только начал экспериментировать с этим. 🙂 Спасибо!