Ваш код не работает, потому что F # обобщает тип аргументов для параметра типа. Я думаю, что вы не можете динамически проверить, можно ли преобразовать тип 'a * 'b
в тип MyType1 * MyType2
(хотя это немного смущает меня). В любом случае вы можете написать функцию, которая принимает два аргумента типа obj
и проверяет их отдельно, используя два шаблона :?
:
type MyType1 = A | B of float
type MyType2 = C | D of int
let func (x:obj) (y:obj) =
match (x, y) with
| (:? MyType1 as x1), (:? MyType1 as x2) ->
printfn "%A %A" x1 x2
| _ ->
printfn "something else"
func A (B 3.0) // A B 3.0
func A (D 42) // something else
В любом случае, было бы интересно узнать, почему вы хотите это сделать? Там может быть лучшее решение ...
РЕДАКТИРОВАТЬ (2) Итак, из всех 4 двухэлементных комбинаций T1
и T2
вам нужна функция, которая может принимать 3. Это правильно (T1 * T1
, T1 * T2
а T2 * T2
)? В этом случае вы не можете написать полностью безопасную функцию карри, потому что тип второго аргумента будет «зависеть» от типа первого аргумента (если первый аргумент имеет тип T2
, то второй аргумент также должен быть T2
(в противном случае это может быть T1
тоже)).
Вы можете написать безопасную функцию без каррирования, которая принимает аргумент следующего типа:
type MyArg = Comb1 of T1 * T1 | Comb2 of T1 * T2 | Comb3 of T2 * T2
Тип функции будет MyArg -> string
.
Если вам нужна функция с карри, вы можете определить тип, который позволит вам использовать либо T1
, либо T2
в качестве первого и второго аргумента.
type MyArg = First of T1 | Second of T2
Тогда ваша функция карри будет MyArg -> MyArg -> string
. Но обратите внимание, что если не разрешена одна комбинация типов аргументов (если я вас правильно понимаю, T2 * T1
не должно быть разрешено). В этом случае ваша функция просто должна будет сгенерировать исключение или что-то в этом роде.