Подтвердить что ты не робот

Структуры данных с циклическими зависимостями в haskell

Я пытаюсь реализовать простой синтаксический анализатор в haskell, используя библиотеку parsec (для учебных целей). Поэтому я написал кучу структурных данных и связанных с ними функций следующим образом:

data SourceElement 
    = StatementSourceElement Statement
    | FunctionSourceElement FunctionName FunctionBody

data Statement 
    = IfStatement Expr Statement Statement
    | WhileStatement Expr Statement

data FunctionBody = FunctionBody [SourceElement]

parseSourceElement :: Parser SourceElement
parseSourceElement = ...

parseFunctionBody :: Parser FunctionBody
parseFunctionBody = ...

Он отлично работает. Теперь я хочу разбить этот материал на два модуля для разделения структур данных FunctionBody и Statement (из-за проблем с читабельностью). Но я не могу! Причина заключается в циклической зависимости между SourceElement и FunctionBody.

Итак, есть ли способ решить эту проблему?

4b9b3361

Ответ 1

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

module Function where 

data FunctionBody e = FunctionBody [e]

parseFunctionBody :: Parser e -> Parser (FunctionBody e)

и

module AST where

data SourceElement
    = StatementSourceElement Statement
    | FunctionSourceElement FunctionName (FunctionBody SourceElement)

Таким образом, взаимная рекурсия абстрагируется на простую рекурсию + параметризацию. Я думаю, что параметризация по крайней мере так же важна, как разделение разных вещей на разные файлы, поэтому это выглядит как приятный (и довольно раздражающий), что один заставляет другого.

Ответ 2

Haskell фактически позволяет рекурсивные модули, а GHC поддерживает их (с небольшим неудобством писать файлы .hs-boot). См. Как скомпилировать взаиморекурсивные модули.

Я не вижу ничего плохого в использовании этой функции здесь.