Haskell:在单子排序中使用列表理解

Haskell:在单子排序中使用列表理解,haskell,monads,Haskell,Monads,我正在阅读这篇关于a的文章,作为一名新手,我无法理解以下结构: newtype Parser a = Parser (String -> [(a, String)]) instance Monad Parser where return a = Parser (\cs -> [(a,cs)]) p >>= f = Parser (\cs -> concat [parse (f a) cs’ |

我正在阅读这篇关于a的文章,作为一名新手,我无法理解以下结构:

newtype Parser a = Parser (String -> [(a, String)])

instance Monad Parser where
  return a = Parser (\cs -> [(a,cs)])
  p >>= f  = Parser (\cs -> concat [parse (f a) cs’ |
                               (a,cs’) <- parse p cs])

parse :: Parser a -> String -> [(a,String)]
parse (Parser p) = p
newtype解析器a=解析器(字符串->[(a,字符串)])
实例Monad解析器,其中
返回a=Parser(\cs->[(a,cs)])
p>>=f=Parser(\cs->concat[parse(fa)cs'|
(a,cs')字符串->[(a,字符串)]
解析(解析器p)=p
案文中说:

使用由parse(Parser p)=p定义的解析器的解构器函数,解析器p>>=f首先将解析器p应用于参数字符串cs,以给出形式(a,cs')的结果列表,其中a是值,cs'是字符串。对于每一对,fa是应用于字符串cs'的解析器

为什么是(f a)而不是f解析器?为什么传递“a”是必需的?

用monad
解析器实例化的
(>=)
类型具有以下类型签名:

(>>=) :: Parser a -> (a -> Parser b) -> Parser b
因此,当定义
p>=f
时,
p
具有类型
解析器a
f
具有类型
a->解析器b
。这就是为什么
fa
是解析器而不是
f
f
是从
a
解析器b
的函数

这样做的原因是,如果没有它,我们可以组合解析器…但我们永远无法在下一次解析中使用前一个解析器的结果!通过向前传递前一个解析器的结果,我们可以从多个解析器的结果中构建数据,例如:

parseTwoOf :: Parser a -> Parser (a, a)
parseTwoOf p = p >>= \first -> p >>= \second -> return (first, second)
用monad
解析器实例化的
(>>=)
类型具有以下类型签名:

(>>=) :: Parser a -> (a -> Parser b) -> Parser b
因此,当定义
p>=f
时,
p
具有类型
解析器a
f
具有类型
a->解析器b
。这就是为什么
fa
是解析器而不是
f
f
是从
a
解析器b
的函数

这样做的原因是,如果没有它,我们可以组合解析器…但我们永远无法在下一次解析中使用前一个解析器的结果!通过向前传递前一个解析器的结果,我们可以从多个解析器的结果中构建数据,例如:

parseTwoOf :: Parser a -> Parser (a, a)
parseTwoOf p = p >>= \first -> p >>= \second -> return (first, second)
用monad
解析器实例化的
(>>=)
类型具有以下类型签名:

(>>=) :: Parser a -> (a -> Parser b) -> Parser b
因此,当定义
p>=f
时,
p
具有类型
解析器a
f
具有类型
a->解析器b
。这就是为什么
fa
是解析器而不是
f
f
是从
a
解析器b
的函数

这样做的原因是,如果没有它,我们可以组合解析器…但我们永远无法在下一次解析中使用前一个解析器的结果!通过向前传递前一个解析器的结果,我们可以从多个解析器的结果中构建数据,例如:

parseTwoOf :: Parser a -> Parser (a, a)
parseTwoOf p = p >>= \first -> p >>= \second -> return (first, second)
用monad
解析器实例化的
(>>=)
类型具有以下类型签名:

(>>=) :: Parser a -> (a -> Parser b) -> Parser b
因此,当定义
p>=f
时,
p
具有类型
解析器a
f
具有类型
a->解析器b
。这就是为什么
fa
是解析器而不是
f
f
是从
a
解析器b
的函数

这样做的原因是,如果没有它,我们可以组合解析器…但我们永远无法在下一次解析中使用前一个解析器的结果!通过向前传递前一个解析器的结果,我们可以从多个解析器的结果中构建数据,例如:

parseTwoOf :: Parser a -> Parser (a, a)
parseTwoOf p = p >>= \first -> p >>= \second -> return (first, second)


我不确定最后一段和代码块是否非常清楚,但我现在想不出更好的解释方法。我们也可以用应用程序解析器来构建东西,但现在,大多数流行的解析库都是一元的。@dfeuer:我更想说的是,如果要实现这个值,还需要用到其他地方如果所有结果都只用于最后的
返回
,那么
应用
就足够了:
parsetwof p=(,)p
@user3237465:正如我对dfeuer所说的,是的,我很清楚
应用的
已经足够了——我不是想说
单子的力量是必要的,而是说如果你想
=
能够做的事情多于
所能做的,你就不能放弃
a
的价值。我不是我不确定最后一段和代码块是否非常清楚,但我现在想不出更好的解释方法。我们也可以用应用程序解析器来构建东西,但现在,大多数流行的解析库都是一元的。@dfeuer:我更想说的是,如果它是u,那么这个值需要用到某个地方seful,因为否则你最终得到的东西只有
>
的功能。如果所有结果都只在最后的
返回中使用,那么
Applicative
就足够了:
parsetwof p=(,)p
@user3237465:正如我对dfeuer所说的,是的,我很清楚
应用的
已经足够了——我不是想说
单子的力量是必要的,而是说如果你想
=
能够做的事情多于
所能做的,你就不能放弃
a
的价值。我不是我不确定最后一段和代码块是否非常清楚,但我现在想不出更好的解释方法。我们也可以用应用程序解析器来构建东西,但现在,大多数流行的解析库都是一元的。@dfeuer:我更想说的是,如果它是u,那么这个值需要用到某个地方seful,因为如果所有结果仅用于最终的
返回