16

我很难理解为什么这两个片段在所谓的“穷人严格分析”下会产生不同的结果。

第一个示例使用data(假设一个正确的 Applicative 实例):

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示例没有。

我已经阅读了 thisthisthis,但对它们的理解不够深入,无法理解为什么第一个示例未定义。在我看来,在这个例子中,newtype比答案懒惰data,与答案所说的相反。(至少还有一个人也对此感到困惑)。

为什么切换 fromdatanewtype改变这个例子的定义?


这是我发现的另一件事:使用这个 Applicative 实例,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上面的解析器不会输出 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
4

2 回答 2

22
于 2012-11-26T15:16:12.610 回答
11
于 2012-11-26T15:16:50.450 回答