Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[12]

£ то

св а: =з

14. РЕШЕНИЯ ДЛЯ УПРАЖНЕНИЙ

1)Символ равный а удовлетворяет условию равенства а:

symbol a = satisfy (== a)

2)Поскольку <\> является версией ++ более высокого порядка, то он гораздо более эффективно вычисляется в случае ассоциации вправо.

3)Функция just может быть написана с использованием списков следующим образом:

just p xs= [([], v) (ys, v) <- p xs, null ys]

4)Оператор <*> является правоассоциативным, таким образом выражение a <*> b <*> c <*> d на самом деле означает a <*> (b <*> (c <*> d)), что объясняет структуру результата.

5)Парсер epsilon возвращает пустой кортеж в качестве дерева разбора. Функция const Nil применена к результату, отбрасывая таким образом пустой кортеж и заменяя его значением Nil. Вместо epsilon <@ const Nil мы можем также написать succeed Nil.

6)Без скобок мы получим open *> (parens <* (close <*>parens)), и мы лишь сохраним результат первого рекурсивного вызова парсера parens.

7)Функции parens и nesting могут быть написаны как частичная параметризация функции foldparens, обеспечивая применение функций к первой и второй альтернативам:

parens = foldparens Bin Nil nesting = foldparens (max . (1 +)) 0

8)Без преобразователя just в списке благоприятных исходов окажутся только варианты частичного разбора:

? nesting "()(())()"

[([], 2), ("()", 2), ("(())()", 1), ("()(())()", 0)]

? nesting "())"

[(")", 1), ("())", 0)]

9)Пустая альтернатива идёт последней, потому что комбинатор <{> использует конкатенацию списков для объединения списков благоприятных исходов. Это также справедливо и для рекурсивных вызовов; таким образом первыми идут все три символа «а», полученные в результате «жадного» разбора, затем идут два символа «а» и единственный остаток строки, далее один символ «а» и в конце концов пустой результат с нетронутой исходной строкой в качестве необработанной части строки.

ФП 02005-06 01

Лист 37

Копиоова Формат


10)Мы определили <:*> как сокращенную запись заключительной обработки результата работы <*> функцией list:

p <:*> q= p <*> q <@ list

Тогда мы можем определить

many p= p <:*> many p <> succeed []

11)Комбинатор many1 может быть определен с использованием комбинатора many:

many1 p =

sequence :: sequence =

choice choice =

token token

Parser s a -> Parser s [a] p <*> many p <@ list

[Parser s a] -> Parser s [a]

foldr (<:*>) (succeed [])

[Parser s a] -> Parser s a foldr (<>) fail

Eq [s] => [s] -> Parser s [s] sequence . map symbol

14) Такое определение было дано для chainl:

chainl chainl p s

Parser s a -> Parser s (a -> a -> a) -> Parser s a p <*> many (s <*> p) <@ uncurry (foldl (flip ap2))

Чтобы получить chainr необходимо заменить foldl на foldr, поменять местами flip и fold, заменить ap2 на ap1 и переупорядочить распределение many, полученного применением операторов <*>:

chainr chainr p s

Parser s a -> Parser s (a -> a -> a) -> Parser s a many (p <*> s) <*> p <@ uncurry (flip (foldr ap1))

Вспомогательные функции:

ap2 (op, y) ap1 (x, op)

Cop4 y)

15) Самым простым способом явного анализа случаев является:

integerParser Char Int

integer = option (symbol -)<*> natural <@ f where f ([], n)= n

f ( , n)= -n

Однако наиболее удачным является использование оператора <?@, возвращающего функцию тождественности или отрицания в зависимости от наличия или отсутствия знака минус, которая в конце концов применяется к натуральному числу:

ФП 02005-06 01

Лист 38

№ докум.

Копиоова Фоомат


integerParser Char Int

integer = (option (symbol -) <?@ (id,const negate)) <*> natural <@ ap where ap (f, x) = f x

16)Числом в плавающей точкой является число с фиксированной точкой с необязательным порядком числа:

float:: Parser Char Float

float = fixed <*>

(option (symbol E *> integer) <?@ (0, id)) <@ f

where f (m, e) = m * power e

power e e < 0 = 1.0 / power (-e)

otherwise = fromlnteger (10 Л e)

17)Так было бы здорово:

chainl p s = q

where q = (option (q <*> s) <?@ (id, apl)) <*> p <@ ap

Увы, эта функция не будет работать...

18)Разбираемый символ s отбрасывается, а вместо него подставляется пустой список. Затем функция Node s применяется к пустому списку, получая в результате Node s [], что является терминальной вершиной в дереве разбора.

ФП 02005-06 01

Лист 39

№ докум.

Копиоова Фоомат



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13]