Преобразовать строку в конструктор типов в Haskell - PullRequest
7 голосов
/ 17 ноября 2011

Кто-нибудь знает, есть ли в Haskell функция, которая делает что-то вроде этого:

"Int" -> Int

"String" -> String

"Bool" -> Bool

т.е.он берет строковое представление имени конструктора типа и преобразует его в фактический конструктор типа, как в выражении, так и в шаблоне.

edit: Моя общая цель - упростить что-то вроде:

transExp (Add exp1 exp2) vars
  = transExp exp1 vars ++ transExp exp2 vars ++ [IAdd]

transExp (Sub exp1 exp2) vars
  = transExp exp1 vars ++ transExp exp2 vars ++ [ISub]

В одно совпадение с шаблоном, поэтому в основном преобразуйте Add или Sub в строку, добавьте "I" впереди и преобразовайте его обратно в тип.

Ответы [ 4 ]

10 голосов
/ 17 ноября 2011

Существует гораздо лучший способ реорганизовать ваш код здесь без каких-либо шаблонов Haskell или рефлексов, просто соединив ваши Add и Sub дела в одно:

data BinOp = Add | Sub | ...

data Expr = ...
          | BinOp BinOp Expr Expr
          | ...

transExp (BinOp op exp1 exp2) vars
    = transExp exp1 vars ++ transExp exp2 vars ++ [transOp op]
...

transOp Add = IAdd
transOp Sub = ISub

Таким образом, мы 'Вы используете тип данных, чтобы непосредственно выразить тот факт, что бинарные операторы связаны между собой и, следовательно, имеют схожие переводы.Вы можете по-прежнему использовать сопоставление с шаблоном на BinOp Add exp1 exp2, если хотите создать специальный случай для добавления куда-либо.

2 голосов
/ 17 ноября 2011

В каком контексте? Есть Template Haskell и Data.Typeable, но для действительно полезного ответа вам нужно предоставить более подробную информацию.

0 голосов
/ 17 ноября 2011

Вы не можете сделать это, потому что строки являются данными времени выполнения, и типы должны быть полностью разрешены во время компиляции.Лучшее, что вы, вероятно, можете сделать с вашим примером - это вспомогательная функция для устранения некоторого дублирования:

helper exp1 exp2 vars op = transExp exp1 vars ++ transExp exp2 vars ++ [op]
transExp (Add exp1 exp2) vars = helper exp1 exp2 vars IAdd
transExp (Sub exp1 exp2) vars = helper exp1 exp2 vars ISub

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

В общем, сопоставление с образцом - это то, что работает со структурами типов, поэтому оно должно быть прописано в типе компиляции против конструкторов конкретных типов.Это цена, которую вы должны заплатить за действительно надежную систему статического типа.

0 голосов
/ 17 ноября 2011

Ну, вот в чем проблема.

"String" -> String

В Хаскел-ланде это бред, потому что "String" - это значение, а String - это тип. Так что вы можете попробовать это:

String -> a

Это не делает то, что вы хотите. Вы должны научиться читать сигнатуры типов, потому что, если вы не можете читать сигнатуры типов, вы будете серьезно повреждены в Haskell. Указанный выше тип означает: «Дайте мне строку, и я могу дать вам значение любого типа, который вы запрашиваете». В прелюдии есть функция с этой подписью, она называется error, а это не то, что вам нужно.

Звучит так: Вы хотите что-то вроде этого:

String -> TypeRep

Извините, такой функции нет. TypeRep не создает экземпляр класса Read.

Что вы на самом деле пытаетесь сделать здесь? Если вы сообщите нам, что вы на самом деле пытаетесь сделать, мы можем помочь вам с этой проблемой, а не пытаться помочь с этим проблема.

...