Как проверить цитируемое имя конструктора данных в шаблоне Haskell? - PullRequest
3 голосов
/ 27 августа 2011

Я пытаюсь выучить какой-нибудь шаблон Haskell.В качестве упражнения я написал функцию, которая может генерировать такие вещи, как isLeft и isRight (вдохновленный этим вопросом ).Вот моя скромная попытка:

isA connam = do
    ConE nam <- connam
    nn <- newName "p"
    lamE [varP nn] $ caseE (varE nn) [
                       match (conP nam [wildP]) ( normalB [| True |] ) [],
                       match wildP ( normalB [| False |] ) [] 
                     ]

Проблема в том, что она работает только с конструкторами с одним аргументом.Виновником является шаблон conP nam [wildP].В идеале это должно выглядеть как conP nam (replicate (numArgs nam) wildP), где numArgs - это функция, возвращающая количество аргументов конструктора.Но как мне написать такую ​​функцию?Я предполагаю, что мне нужно получить доступ к соответствующему объявлению данных, но я не знаю, как это сделать.

Есть еще один вопрос об этой самой функции здесь .

1 Ответ

7 голосов
/ 27 августа 2011

Хотя вы можете использовать reify и исследовать тип для определения арности конструктора данных, гораздо проще генерировать независимый от арности код с использованием шаблона записи:

isFoo :: Bar -> Bool
isFoo p = case p of
    (Foo {}) -> True     -- Valid no matter what the arity of Foo is
    _        -> False

Это можно сделать, заменив conP на recP в своем коде.

isA connam = do
    ConE nam <- connam
    nn <- newName "p"
    lamE [varP nn] $ caseE (varE nn) [
                       match (recP nam []) ( normalB [| True |] ) [],
                       match wildP ( normalB [| False |] ) [] 
                     ]
...