Я пытаюсь разобрать sgf-файлы (файлы, описывающие игры). В этих файлах есть пары ключевых значений формы (в спецификации sgf они называются значениями свойств и свойств свойства, но я использую ключ и значение в надежде, что люди узнают, о чем я говорю при чтении названия):Parsec: пары ключевых значений, где тип значения зависит от ключа
key[value]
или
key[value1][value2]...[valuen]
То есть, может быть 1 или много значений. Улов состоит в том, что тип значения зависит от ключа. Так, например, если ключ B
(для игры черный камень в движении). Значение должно быть координатой, описываемой двумя буквами, например: B[ab]
. Также может быть, что ключ AB
(для добавления нескольких черных камней, для настройки платы), тогда это список таких координат: AB[ab][cd][fg]
. Также может быть, что ключ C
(для комментария). Тогда значение представляет собой только строку C[this is a comment]
.
Конечно, это может быть описано по типу
type Property = (String, [String])
Но я думаю, что было бы лучше, чтобы иметь что-то вроде
data Property = B Coordinate | AB [Coordinate] | C String ...
Или, может быть, какой-либо другой тип, который лучше использует систему типов и не будет требовать, чтобы я постоянно конвертировал в строки и из них.
Проблема в том, что тогда мне понадобится синтаксический анализатор, который в зависимости от типа ключа возвращает другой тип значения, но я думаю, что это вызовет проблемы типа, поскольку парсер может возвращать только один тип значения.
Как бы вы разобрали что-то вроде этого?
Монадически. Разберите ключ (тип этого синтаксического анализа: 'm Key').Затем подайте этот ключ на функцию, которая анализирует регистр на ключе, и выбирает соответствующий синтаксический анализатор на основе ключа (тип: 'Key -> m Property'); вы можете использовать '(>> =)' для этого или просто do-notation: 'do {key <- parseKey; ключевой ключ {KeyB -> parseB; KeyAB -> parseAB; keyC -> parseC}} ' –
Второе поколение @Rhymoid. Это также, по сути, является разницей между аппликативным функтором и монадой. С помощью монады вы можете использовать информацию, которую только что разобрали, чтобы решить, как вы собираетесь разбирать то, что будет дальше. К счастью, Parsec является примером как аппликации, так и монады. Очень наглядный пример разницы! – kqr