2017-02-03 3 views
1

Я пытаюсь создать парсер для упрощенного DSL.Проблема с жесткими переменными типа

Я бегу в проблему с помощью следующей функции:

procP :: ((a->Bool) -> [a] -> Bool) -> String -> Comperator -> ([String] -> Bool) 
procP q v c = 
    case c of 
     NumE -> q ((==) . unMay . readDouble $ v) . mapMaybe readDouble 
     NumNE -> q ((/=) . unMay . readDouble $ v) . mapMaybe readDouble 
     NumLTE -> q ((<=) . unMay . readDouble $ v) . mapMaybe readDouble 
     NumLT -> q ((<) . unMay . readDouble $ v) . mapMaybe readDouble 
     NumGTE -> q ((>=) . unMay . readDouble $ v) . mapMaybe readDouble 
     NumGT -> q ((>) . unMay . readDouble $ v) . mapMaybe readDouble 
     Exists -> q notBlanks 
     DatE -> q ((==) . unMay . p_date $ v) . mapMaybe p_date 
     DatNE -> q ((/=) . unMay . p_date $ v) . mapMaybe p_date 
     DatLTE -> q ((<=) . unMay . p_date $ v) . mapMaybe p_date 
     DatLT -> q ((<) . unMay . p_date $ v) . mapMaybe p_date 
     DatGTE -> q ((>=) . unMay . p_date $ v) . mapMaybe p_date 
     DatGT -> q ((>) . unMay . p_date $ v) . mapMaybe p_date 
     TxtE -> q (==v) 
     TxtME -> (q (==v)) . map (rTrim) 
     TxtNME -> (q (/=v)) . map (rTrim) 
     TxtNE -> q (/= v) 

Пробой здесь выглядит следующим образом:

q некоторая функция, которая работает как any от прелюдии. Существует несколько разных вариантов, но подпись типа должна быть более или менее одинаковой - с учетом предиката и списка, возвращает bool.

v - это строковый ввод для целей сравнения, он помогает построить предикат.

c - это токен, созданный парсером, который представляет, какое сравнение мы должны использовать в предикате.

unMay - это глупая функция взлома, чтобы «развернуть» значение Just на Nothing.

readDouble и p_date являются функции, которые принимают String и возвращают либо Maybe Day или Maybe Double, соответственно.

Дизайн намерения здесь является то, что мы используем Comparator маркер, чтобы сказать нам, какой тип изменить входной String S внутренне, так что я могу выбрать, сравнить со значением, как String, Day, или Double, соответственно.

Относительно супер базовой версии того, что делает Perl с == против eq, но с меньшим принуждением и более неприятными сообщениями об ошибках.

Проблема у меня в том, что это не тип проверки, поскольку предикат получения передается q заканчивает представление, как тип Double->Bool вместо a->Bool, и поэтому я получаю ошибку о том, как a жесткая переменная типа ,

Ошибка более или менее имеет смысл для меня, но у меня много проблем, думая о том, как обойти эту проблему.

Есть ли у кого-нибудь советы о том, как переструктурировать это?

+0

Возможный дубликат [Haskell: GHC не может вывести тип. Жесткая переменная типа, связанная с ошибкой сигнатуры типа] (http://stackoverflow.com/questions/22778098/haskell-ghc-cannot-deduce-type-rigid-type-variable-bound-by-the-type-signature) – jberryman

+1

Должен ли v также быть 'rTrim''d для' TxtME' и 'TxtNME'? – Gurkenglas

+0

@Gurkenglas - Хороший улов. Благодаря! –

ответ

4

Rank2Types Включите (например, поставив {-# LANGUAGE Rank2Types #-} в верхней части файла) и написать

--   vvvvvvvvv difference is here 
procP :: (forall a. (a->Bool) -> [a] -> Bool) -> String -> Comperator -> ([String] -> Bool) 
+0

Спасибо! Это работало отлично и было гораздо меньше работы, чем я боялся. –

Смежные вопросы