Я хотел бы знать, что можно считать лучшей практикой в отношении монады State
. Я также открыт для любых других предложений.
У меня есть бинарный файл для разбора. Он содержит разные заголовки, которые необходимо проанализировать, чтобы иметь возможность прочитать весь файл.
Таким образом, заголовки можно анализировать, используя только состояние из анализа.
data ParseState = ParseState {
offset :: Int64
buffer :: B.ByteString
endianness :: Endianness
pointerSize :: MachineWord
positionStack :: [Int64]
}
Затем эти данные используются в State
монаде.
type Parser a = State ParseState a
Это может идеально подойти для синтаксического анализа заголовка. Но как только я хочу разобрать полный файл, мне нужна информация из шапки, чтобы иметь возможность правильно прочитать файл.
data Header = Header {
txtOffset :: Int64,
stringOffset :: Int64
}
Мне нужна информация заголовка, чтобы продолжить синтаксический анализ файла.
Моя идея состояла в том, чтобы использовать новую монаду состояния, которая находится поверх предыдущей. Итак, у меня есть новая монада StateT:
type ParserFullState a = StateT Header (State ParserState) a
Таким образом, я могу продолжить и построить целый набор функций парсера, используя новый преобразователь состояния. Я также мог бы сделать это по-другому и добавить заголовок к исходным данным ParseState
.
Плюсы, которые я вижу при добавлении заголовка обратно в ParserState
, следующие:
- Тип возвращаемого значения функции синтаксического анализатора — универсальный.
- Нет необходимости вызывать
lift
для доступа к примитиву парсера.
Минусы я вижу следующие:
- Нет различия между синтаксическим анализатором более высокого уровня и примитивом более низкого уровня.
- Мы не можем четко сказать, когда заголовок полностью проанализирован, а когда нет. Таким образом, модификация парсера становится более хрупкой.
Каково ваше предложение? Должен ли я использовать преобразователь состояния, должен ли я добавить заголовок в исходное состояние или что-то еще?
Спасибо.
data ParseState' = Initial ParseState | Later ParseState Header
или какой-либо другой АТД, который подходит для вашей задачи, чтобы у вас было только одно состояние, которое может представлять ваше начальное состояние синтаксического анализа, а затем, когда вам понадобитсяHeader
, у вас есть информация какParseState
, так иHeader
, и они хранятся отдельно? Вам просто нужноput (Later parseState header)
, когда у вас есть информация заголовка. - person bheklilr   schedule 14.08.2014