Я пытаюсь понять, почему эти два фрагмента дают разные результаты при так называемом "анализе строгости человека".
В первом примере используется data
(при условии правильного аппликативного экземпляра):
data Parser t a = Parser {
getParser :: [t] -> Maybe ([t], a)
}
> getParser (pure (,) <*> literal ';' <*> undefined ) "abc"
*** Exception: Prelude.undefined
Второй использует newtype
. Нет другой разницы:
newtype Parser t a = Parser {
getParser :: [t] -> Maybe ([t], a)
}
> getParser (pure (,) <*> literal ';' <*> undefined ) "abc"
Nothing
literal x
- это синтаксический анализатор, который успешно использует один токен ввода, если его аргумент соответствует первому токену. Поэтому в этом примере он терпит неудачу, поскольку ;
не соответствует a
. Тем не менее, пример data
все еще видит, что следующий синтаксический анализатор undefined, в то время как пример newtype
не работает.
Я прочитал этот, этот и это, но не понимайте их достаточно хорошо, чтобы понять, почему первый пример - undefined. Мне кажется, что в этом примере newtype
более ленив, чем data
, что противоположно сказанному. (По крайней мере еще один человек тоже был смущен).
Почему переход от data
в newtype
изменяет определенность этого примера?
Вот еще одна вещь, которую я обнаружил: с этим аппликативным экземпляром анализатор data
выше выводит undefined:
instance Applicative (Parser s) where
Parser f <*> Parser x = Parser h
where
h xs =
f xs >>= \(ys, f') ->
x ys >>= \(zs, x') ->
Just (zs, f' x')
pure a = Parser (\xs -> Just (xs, a))
тогда как с этим экземпляром анализатор data
выше не выводит undefined (при условии правильного экземпляра Monad для Parser s
):
instance Applicative (Parser s) where
f <*> x =
f >>= \f' ->
x >>= \x' ->
pure (f' x')
pure = pure a = Parser (\xs -> Just (xs, a))
Полный фрагмент кода:
import Control.Applicative
import Control.Monad (liftM)
data Parser t a = Parser {
getParser :: [t] -> Maybe ([t], a)
}
instance Functor (Parser s) where
fmap = liftM
instance Applicative (Parser s) where
Parser f <*> Parser x = Parser h
where
h xs = f xs >>= \(ys, f') ->
x ys >>= \(zs, x') ->
Just (zs, f' x')
pure = return
instance Monad (Parser s) where
Parser m >>= f = Parser h
where
h xs =
m xs >>= \(ys,y) ->
getParser (f y) ys
return a = Parser (\xs -> Just (xs, a))
literal :: Eq t => t -> Parser t t
literal x = Parser f
where
f (y:ys)
| x == y = Just (ys, x)
| otherwise = Nothing
f [] = Nothing