我挣扎理解为什么这两个片段,所谓“穷人的严格分析”下产生不同的结果。
第一个例子使用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
例如仍然认为,未来解析器是不确定的,而newtype
例子没有。
我读过这个 , 这个和这个 ,但不明白他们不够好,知道为什么第一个例子是不确定的。 在我看来,在这个例子中, newtype
不止懒惰data
,答案是什么的对面说。 (至少一人已被此迷惑过)。
为什么从没有交换data
来newtype
改变这个例子的definedness?
下面是我发现的另一件事情:使用此应用型情况下, data
上面的输出解析器未定义:
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
解析器以上不输出不确定的(假设为正确的单子实例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