Как сделать эквивалент сопоставления шаблонов для собственных типов .NET?

let print_type_c (x: Type)= 
    if x = typeof<Int32> then "int"
    elif x = typeof<Single> then "float"
    elif x = typeof<Tuple<_>> then "tuple"
    elif x = typeof<FSharpFunc<Tuple<'inp>,'out>> then "function..."
    else failwithf "Not supported(%A)" x

print_type_c (typeof<int>) // prints int
print_type_c (typeof<float32>) // prints float
print_type_c (typeof<int*int>) // throw an exception

Я пытаюсь создать примитивные цитаты F # для компилятора Cuda, и мне нужно выяснить, как преобразовать типы кортежей в типы структур C в объявлениях функций, но я действительно не знаком с тем, как работает механизм .NET. Разочаровывает то, что кавычки F# не возвращают вам хороший AST, основанный на размеченных объединениях, который сделал бы все явным, но если я не хочу сам выполнять проверку типов, мне придется поработать с этим.

Я спрашиваю - есть ли способ к дрянному фрагменту кода выше с сопоставлением шаблонов на .NET Types, потому что вышеизложенное явно не работает.

Изменить: вопрос не является дубликатом, потому что этот связанный вопрос спрашивает, как печатать свойства записей F #, а я спрашиваю, как печатать типы собственных типов .NET (включая функции) внутри котировок F #. Визуальное сканирование принятого ответа здесь и там должно показать, что они совершенно разные и даже не используют одни и те же функции.


person Marko Grdinic    schedule 20.10.2016    source источник
comment
Как это не работает?   -  person Fyodor Soikin    schedule 20.10.2016
comment
@asibahi Нет, я так не думаю. См. мой комментарий Федору в его ответе. Я хочу избежать использования typeof для проверки типов.   -  person Marko Grdinic    schedule 20.10.2016
comment
@MarkoGrdinic Я не думаю, что вы можете проверить тип объекта во время компиляции.   -  person asibahi    schedule 20.10.2016


Ответы (1)


Вывод типа времени выполнения? О типах, неизвестных во время компиляции? Нет, извините, не существует, вам придется построить его самостоятельно.

Чтобы проверить, является ли конкретный тип экземпляром определенного универсального типа, вам нужно сначала увидеть, является ли он универсальным, а затем получить его универсальное определение и сравнить его:

if x.IsGenericType && (x.GetGenericTypeDefinition() = typeof<System.Tuple<_>>.GetGenericTypeDefinition()) then "tuple" else "not"

Обратите внимание, что существует не один тип Tuple, а множество — Tuple<_>, Tuple<_,_>, Tuple<_,_,_> и так далее — до 8.

То же самое касается FSharpFunc:

if x.IsGenericType && (x.GetGenericTypeDefinition() = typeof<FSharpFunc<_,_>>.GetGenericTypeDefinition()) then "function" else "not"

Чтобы получить общие аргументы типа, используйте .GetGenericArguments():

if x.IsGenericType && (x.GetGenericTypeDefinition() = typeof<FSharpFunc<_,_>>.GetGenericTypeDefinition()) 
then 
    sprintf "function %s -> %s" (x.GetGenericArguments().[0].Name) (x.GetGenericArguments().[1].Name)
else 
    "not function"
person Fyodor Soikin    schedule 20.10.2016
comment
Я недостаточно хорошо объяснил. Да, это правда, что я делаю вывод типа во время выполнения выше, но я действительно хочу этого избежать. В фрагменте кода типа F# все типы фактически известны во время компиляции. Итак, как мне их получить, чтобы я мог распечатать их в стиле языка C для объявлений переменных? Я бы предпочел не делать каждую комбинацию Tuple для каждого отдельного типа, если бы мог помочь. - person Marko Grdinic; 20.10.2016
comment
Печать в стиле C происходит во время выполнения. Следовательно, печатаемые типы должны быть представлены во время выполнения. - person Fyodor Soikin; 20.10.2016
comment
Хорошо ... Я почти даже не хотел его тестировать, но ваш ответ действительно дает мне все, о чем я просил. Спасибо. - person Marko Grdinic; 20.10.2016