Сравнение шаблонов с монадическим результатом? - PullRequest
3 голосов
/ 24 августа 2011

Я изучаю Haskell и хочу использовать «readHex», который согласно Hoogle имеет тип:

readHex :: Num a => ReadS a

Как вы "извлекаете" результат из такой функции? Каков наиболее распространенный способ сопоставления с шаблоном с правильным конструктором, т. Е. [(A, "")] ??

LiftM и поднятие в целом, кажется, имеют некоторый смысл, но я теряюсь, когда дело доходит до «разматывания» монадического стека.

Ответы [ 4 ]

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

Чтобы ответить на общий вопрос в общих чертах, способ only для извлечения значений из конструктора данных - это сопоставление с образцом.Некоторые типы данных поставляются с функциями, которые извлекают значения для вас, но сами эти функции реализуются с помощью сопоставления с образцом или вызывают другие функции, & c.Абстрактные типы данных, такие как Data.Map.Map или IO, которые хотят скрыть свою внутреннюю структуру, все еще требуют сопоставления с образцом для работы;Разница в том, что они не экспортируют свои конструкторы из модуля, который их определяет, поэтому вам нужно работать только с другими функциями, определенными в модуле, и выполняемыми ими операциями.

Чтобы ответить на конкретный вопрос,ReadS определяется как так:

type ReadS a = String -> [(a, String)]

Так что это просто синоним типа.Вам не нужно ничего извлекать из самого ReadS, это просто сокращение или псевдоним.Фактический тип - [(a, String)], с которым вы можете работать так же, как и с любым другим, используя списки, кортежи, String s и т. Д.

Кроме того, ReadS не является Monad.Это синоним типа для чего-то, что не является экземпляром Monad, и фактически не может быть непосредственно преобразовано в один (нет способа написать [(a, String)] в форме, необходимой для объявления экземпляра).

2 голосов
/ 25 августа 2011

Тип ReadS a является синонимом String -> [(a, String)]. Это функция, которая принимает одну входную строку и выдает список совпадений - первый элемент является результирующим значением, а второй - строкой, которая соответствует. В вашем случае, скорее всего, есть только одно совпадение, поэтому я предлагаю вам использовать его так:

case readHex str of
  ((num,""):_) -> ...
  _            -> error ...
2 голосов
/ 25 августа 2011

Здесь нет ничего монадического.ReadS - это просто псевдоним типа ( ссылка ).

Если вы выполните:

> readHex "41A"

Тогда вы получите одноэлементный список кортежа:

[(1050,"")]

Существует множество способов извлечь значение 1050.Некоторые будут использовать оператор case.Я бы определил вспомогательную функцию, используя listToMaybe:

readHexToVal :: Num a => String -> Maybe a
readHexToVal = listToMaybe . map fst . readHex
0 голосов
/ 26 июля 2014

Вы можете получить результат, используя let:

let ((d, _):_) = readHex "123ab"
...