Типы выглядят по-разному, поскольку для использования состояния в строке rPlace
требуется более общая сигнатура типа, чем разрешает псевдоним типа Router
.(Ваш код в порядке. Но, возможно, нам следует предложить более общий псевдоним в бумеранге ..)
Если вы удалите строку rPlace, вы можете изменить тип сигнатуры состояния на:
state :: Router State
state = xmaph read (Just . show) anyString
Если вы посмотрите более внимательно, я думаю, вы увидите, что state
и articleId
на самом деле идут в одном и том же направлении.
articleId :: Router ArticleId
articleId = xmaph ArticleId (Just . unArticleId) int
Третий аргумент xmaph
указывает, как анализировать некоторые базовыезначение.В случае articleId
он анализирует int
, а для state
он анализирует anyString
.
Первый аргумент xmaph
указывает, как преобразовать это значение в требуемый тип возвращаемого значения.В articleId
мы просто применяем конструктор ArticleId
.В state
мы применяем функцию read
.Но в обоих случаях мы переходим от базового значения к желаемому типу возвращаемого значения:
ArticleId :: Int -> ArticleId
read :: String -> State
Второй аргумент в xmaph
указывает, как преобразовать возвращаемый тип обратно в базовое значение.
show :: State -> String
unArticleId :: ArticleId -> Int
Тем не менее, в любом случае мы не должны использовать здесь «чтение», потому что «чтение» может привести к ошибке и из-за ошибки.Предполагается, что первым аргументом xmaph будет общая функция.
Я загрузил бумеранг 1.3.1, который добавляет новый комбинатор в модуль Strings
с именем readshow
.Эта функция правильно использует экземпляры Read и Show.К сожалению, сообщения об ошибках немного неаккуратны, так как, когда reads
терпит неудачу, он ничего не говорит нам о том, почему или где произошла ошибка.Но это лучше, чем ничего:)
Используя это, вы теперь можете написать:
state :: PrinterParser StringsError [String] o (State :- o)
state = readshow
, если мы предоставим недопустимое состояние, мы теперь получим:
> parseStrings sitemap ["AZ"]
Right (State AZ)
> parseStrings sitemap ["FOEU"]
Left parse error at (0, 0): unexpected FOEU; decoding using 'read' failed.