理解 Haskell 中括号的使用 - 依赖于先前解析器的解析器在使用括号时会出错

问题描述 投票:0回答:1

好吧,我正在尝试学习 Haskell。

这是我的解析器。

import Data.Char
data Parser a = MkParser (String -> Maybe (String, a))

这是一个解析器,它解析一个字符串一次,然后根据它解析的内容,运行另一个解析器。

-- second parse depends on the first
(<<<=) :: Parser a -> (a -> Parser b) -> Parser b
-- a parse, gives Nothing | Just (string, ans depending on a)
(MkParser pa) <<<= k = MkParser sf
    where
        sf inp = case pa inp of
            Nothing -> Nothing
            Just (cs, c) -> unParser (k c) cs

unParser :: Parser a -> String -> Maybe (String, a)
-- applies a parser manually
unParser (MkParser pa) inp = pa inp

现在我在这里使用它(

isDigit
只是检查字符是否是数字,
isAlpha
检查它是否是字母)。我还使用这个基本解析器(解析字符是否是我正在寻找的)

char :: Char -> Parser Char
char wanted = MkParser sf
  where
    sf (c:cs) | c == wanted = Just (cs, c)
    sf _ = Nothing

现在当我这样做时:

t = satisfy isAlpha <<<= \x -> satisfy isDigit <<<= \y -> char x

有效!

但是当我把它放在括号里时

t = satisfy isAlpha <<<= (\x -> satisfy isDigit) <<<= \y -> char x

它给出一个错误,说变量

x
不在范围内......为什么?

我最初只是放置了括号,因为这样更容易阅读。但事实证明我的代码只有在删除括号时才有效。

我尝试使用它并意识到这也有效:

t = satisfy isAlpha <<<= (\x -> satisfy isDigit <<<= \y -> char x)

问题1)但是为什么呢?如果它先执行

(\x -> satisfy isDigit <<<= \y -> char x)
,它就不知道
x
是什么,那么它是如何工作的呢?

问题2)如果不使用括号,评估顺序是什么?

问题 3)为什么我这样做时不起作用

(\x -> satisfy isDigit)

所有问题都是相关的,我确信我只是误解了评估顺序。我曾经用 OOP 语言编程,我觉得我误解了 Haskell 中的括号和求值顺序?

haskell functional-programming
1个回答
0
投票

在你的第一个例子中:

t = satisfy isAlpha <<<= (\x -> satisfy isDigit) <<<= \y -> char x

看起来您正在将

(<<<=)
运算符的左侧和右侧都视为解析操作。

但实际上,左侧是一个解析动作,而右侧是一个函数,它获取前一个解析器的结果,并返回另一个解析动作。

t = parser1 <<<= parser2 <<<= parser3
  where
    parser1 = satisfy isAlpha
    parser2 x = satisfy isDigit
    parser3 y = char x  -- x isn’t in scope

在你的第二个例子中:

t = satisfy isAlpha <<<= (\x -> satisfy isDigit <<<= \y -> char x)

这解决了范围问题,因为它澄清了第三个解析器需要在

x
的范围内,换句话说,它需要在其闭包中包含
x

t = parser1 <<<= function1
  where
    parser1 = satisfy isAlpha
    function1 x = parser2 <<<= function3
      where
        parser2 = satisfy isDigit
        function3 y = char x
© www.soinside.com 2019 - 2024. All rights reserved.