“Программирование В Haskell” ошибка в находившейся функции

Я нахожусь в главе 8 Программирования Graham Hutton в Haskell, и я копирую код и тестирую его в GHC.

Посмотрите слайды здесь: http://www.cis.syr.edu/~sueo/cis352/chapter8.pdf в особенности скользит 15

Соответствующие нормы, которые я скопировал до сих пор:

type Parser a = String -> [(a, String)]
pih_return :: a -> Parser a
pih_return v = \inp -> [(v, inp)]
failure :: Parser a
failure = \inp -> []
item :: Parser Char
item = \inp -> case inp of
                    [] -> []
        (x:xs) -> [(x,xs)]
parse :: Parser a -> String -> [(a, String)]
parse p inp = p inp
sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
           if p x then pih_return x else failure

Я изменил имя return функция от книги до pih_return так, чтобы это не сталкивалось с Вводной частью return функция.

Ошибки находятся в последней функции sat. Я скопировал это непосредственно с книги.

Поскольку можно, вероятно, видеть p функция от Char кому: Bool (например. isDigit) и x имеет тип [(Char, String)], таким образом, это - первая ошибка.

Затем pih_return принимает значение v и возвраты [(v, inp)] где inp a String. Это вызывает ошибку в sat потому что v быть переданным x который не является a Char.

Я предложил это решение, явно включая inp в sat

sat :: (Char -> Bool) -> Parser Char
sat p inp = do x <- item inp
               if p (fst x) then pih_return (fst x) inp else failure inp

Действительно ли это - лучший способ решить проблему?

5
задан Matt Ellen 9 April 2010 в 12:51
поделиться

3 ответа

Первый sat не может работать, Parser должен быть монадой, чтобы использовать ] do обозначение. Чтобы сделать его экземпляром монады, необходимо использовать newtype .

Мне не принадлежит книга, но я полагаю, что автор хотел начать с простого типа синтаксического анализатора, а затем расширить его до полной монады, и я подозреваю, что вы перепутали определения немонадических версий с одним из монада парсера ( sat ) и пропустила объявление экземпляра монады по пути.

Есть код из главы , доступной на веб-сайте автора , где экземпляр монады был определен для Parser .

Если вам нужно написать функцию sat для простого типа Parser , я бы предпочел использовать лямбда-стиль (как элемент ) и избегать монад. полностью (вы заметили, что исходный блок sat do был монадой Parser , а ваш - монадой List ?). И я думаю у вас есть ошибка в вашей sat версии: вместо pih_return (fst x) inp , я думаю, это должно быть pih_return (fst x) (snd x) .

5
ответ дан 14 December 2019 в 01:05
поделиться

Вы не можете использовать нотацию do без монады, и вы не можете создать экземпляр монады, если не используете data или newtype , и вы не можете использовать data или newtype , если не введете раздражающий конструктор значений. Несомненно, конструктор значения был опущен только потому, что он раздражает.

В приведенном ниже примере вы можете видеть, что я использовал newtype и ввел раздражающий конструктор значений Parser . Это то, что заставляет объявление экземпляра работать, и на этом этапе вы можете использовать не только нотацию do , но и стандартные монадические return и fail .

Этот код компилируется без ошибок и предупреждений:

module P
where

newtype Parser a = Parser (String -> [(a, String)])
instance Monad Parser where
  return a = Parser $ \inp -> [(a, inp)]
  fail _   = Parser $ \_   -> []
  Parser f >>= k = Parser $ \inp -> 
     [(b, inp'') | (a, inp') <- f inp, let Parser g = k a, (b, inp'') <- g inp']

item :: Parser Char
item = Parser $ \inp -> case inp of
                          [] -> []
                          (x:xs) -> [(x,xs)]
parse :: Parser a -> String -> [(a, String)]
parse (Parser p) inp = p inp
sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
           if p x then return x else fail "predicate not satisfied"
2
ответ дан 14 December 2019 в 01:05
поделиться

На слайдах отсутствует реализация класса типов Монады для типа Parser .

С этим объявлением запись do верна; x <- item фактически выполняет правильную развёртку из [(Char, String)] в (Char, String) .

Кажется, я не могу получить это определение, не скомпилировав его, чтобы увидеть ошибку, но это начало:

instance Monad (Parser a) where
  return x = pih_return x
  -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b
  p >>= f = \inp -> case p inf of
                      [] -> []
                      (x:xs) -> (f x) xs -- this line is probably wrong
  fail message = [] -- message is ignored
1
ответ дан 14 December 2019 в 01:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: