В F# вы можете определить функцию first
следующим образом:
let first (x, y) = x
Вы можете назвать это так:
first (1, 2)
Вы также можете определить ту же функцию в терминах типа BCL Tuple
:
let first (t:Tuple<_, _ >) = t.Item1
Однако вы не можете вызвать его, используя прежний синтаксис, иначе вы получите следующую ошибку:
error FS0001: The type ''c * 'd' is not compatible with the type 'Tuple<'a,'b>'
Вместо этого вы должны сделать следующее:
first (Tuple<_,_>(1, 2))
Это странно, поскольку скомпилированный код F#, похоже, использует Tuple
для представления своих параметров в любом случае. Так почему же компилятор F# сообщает мне, что типы несовместимы?
Почему все это имеет значение? Ну, в основном я хочу написать метод с перегрузками, поддерживающий кортеж произвольной длины. Это невозможно с синтаксическими кортежами F#, поскольку точное количество аргументов должно быть известно заранее. Однако это кажется возможным при использовании типов BCL Tuple
, потому что они используют прием TRest
, чтобы разрешить кортежи произвольной длины. К сожалению, если я напишу свои перегрузки таким образом, то они не будут работать с синтаксическими кортежами F#, что является конечной целью.
Итак, мой вопрос: почему синтаксические кортежи и кортежи BCL несовместимы? А также, есть ли примеры написания функций и/или методов, которые работают с кортежами произвольной длины на F#?
Конкретное приложение имеет дело с библиотекой бинарного синтаксического анализа на основе вывода типов, которую я пишу. Код можно просмотреть здесь. Вы можете видеть множество перегрузок, которые у меня есть для кортежей, но я не хочу расширять их до какого-то магического числа.