English 中文(简体)
利用Monad Error with Parsec
原标题:Using MonadError with Parsec

我试图与Parsec一道使用MonadError。 下面的法典是:

f5 = do
    char  a 
    throwError "SomeError"

f6 = f5 `catchError` (e -> unexpected $ "Got the error: " ++ e)

ret = runErrorT (runParserT f6 () "stdin" "a")

然而,retLeft “SomeError”,看来是渔获量。 错误具有任何影响。 这里使用莫德埃尔语的正确途径是什么?

我更喜欢使用莫德埃尔多尔语处理帕罗特语,例如,我有:

try (many1 parser1) <|> parser2

如果教区1 在这里失败,教区2将继续,但我只想有一个例外,完全放弃教区。

最佳回答

我的印象是,由于错误原因,你重新尝试使用<代码>MonadError。

在<代码>(many1 parser1) <> parser<2>/code>中,你为避免使用<代码><<>/code>和<>;——如果你不喜欢,使用不同的组合器。 或许像(many1 parser1)”和“>”; parser2(many1 parser1);你当然可以使用>>=(many1 parser1)的结果与parser2的结果合并。)


(说明:在此点之后,目前问题没有真正的好解决办法,只是某些事情为什么会赢得工作......。 希望这可能是(有些是)开明的,但并不期望太多。

更仔细地审查ParsecT / MonadError之间的互动。 我担心它会带来一点点迷惑,我仍不敢真正地确定如何最好地去做被占领土上想要做的事情,但我希望以下一点至少能说明原办法未能取得成功的原因。

首先,请注意it 不能说Parsec是Monad Error的一个实例。 假释是ParsecT在 in门身份时制作的mon; 只有当获得内mon时,ParsecT才会产生蒙德埃尔的事例,而这本身就是莫德埃洛尔与他合作的一个实例。 GHCi互动的相关碎片:

> :i Parsec
type Parsec s u = ParsecT s u Identity
    -- Defined in Text.Parsec.Prim
-- no MonadError instance

instance (MonadError e m) => MonadError e (ParsecT s u m)
  -- Defined in Text.Parsec.Prim
-- this explains why the above is the case
-- (a ParsecT-created monad will only become an instance of MonadError through
-- this instance, unless of course the user provides a custom declaration)

其次,let自称是捕获量的一个工作榜样。 Error and ParsecT。 考虑全球卫生联合会的这一互动:

> (runParserT (char  a  >> throwError "some error") () "asdf" "a" :: Either String (Either ParseError Char)) `catchError` (e -> Right . Right $  z )
Right (Right  z )

这种说明似乎是必要的(这似乎对我来说是直觉的,但与原始问题毫不相关,因此,我赢得了尝试。 整个表达方式由格奥尔蒂斯确定如下:

Either String (Either ParseError Char)

因此,我们定期取得以下成果:<条码>。 Either String monad in place otherwise Identity monad. 由于<代码>Either String 是Monad Error的一个实例,我们可以使用<代码>throwError / submissionsError,但发送到liver Error的投稿人当然必须产生正确的数值。 这对打破司空见惯的例行公事——恐怕。

<>Back to example Code from the question. 这略有不同。 请审查问题定义的<代码>ret的类型:

forall (m :: * -> *) a.
(Monad m) =>
m (Either [Char] (Either ParseError a))

(根据GHCi......指出,我不得不取消独一无二的限制,其编号为{-# LANGUAGE No Mono吗?”

这种类型与<代码>ret做一些事情的可能性有关。 在这方面,我们:

> runParserT ret () "asdf" "a"
Right (Left "some error")

中文无需改动。 恐怕我看不出如何把这 into为有助于打破教区进程的东西。

问题回答

如果你试图用 par子 de灭麻烦,则可能更简单地使用<代码>error,Debug.Trace,或者说什么。

另一方面,如果你需要终止作为您实际方案一部分的某些投入的界限,但由于<代码>try(......)和lt;的建筑,你有的逻辑 ,你应停止并重新思考你的图表,而不是用错误处理的方式 ha。

如果你希望教区在某个时候,而不是其他时候,就终止,那么你的投入流(应当加上)或教区要么就失去了东西,不是解决你的问题。

如果您希望教官能够从非书证错误中 recover取,并尽可能地进行尝试,但当其继续工作时,会以错误终止,那么,你会想考虑除Parsec以外的一些东西,因为它实际上不是为之设计的。 我认为乌得勒支大学的Haskell教区图书馆更方便地支持这种逻辑。

<>Edit:就Parsec本身而言,是Monad Error pro-yes 及其本人的错误处理等于这一功能。 你试图做的是,在Parsec的顶端 error了一个second的错误mon,而且你可能会遇到麻烦,因为通常很难区分“多余”的mon变者。 处理多个国家的僧.是更著名的ward,因此,Parsec(一个国家的僧.)提供了维持习俗状态的功能。

换句话说,把 Parsec 定义成一个错误单子对你没有任何帮助,实际上它通常只会让问题变得更加困难。

如果你需要作为实际方案的一部分终止某些投入的界限,但由于你尝试(......)和“......”而没有这样做; 那么,你在逻辑上就座,你应当停止并重新思考你的克法,而不是以错误处理的方式 ha。

如果你希望教区在某个时间,而不是其他时间,就终止,那么要么从你的投入流中遗漏了一部分东西(应当加上),要么说教子不是解决你的问题。

答案是假设问题在于图表。 但是,如果我用图表为汇编者提供素材,那么图马可处理其他错误。 让我们说一个可变的参照点,即界定的变量。 语言被指定为单一通行证,变数则按所见情况进行评估。 然后,这部书状只是罚款。 教区只是罚款。 但是,由于对图表中指明的错误进行了评估,现有“失败”或“未预料”或不足以处理这一问题。 在不采用较高层次的错误处理的情况下,有办法避开 par堂。





相关问题
Euler Problem in Haskell -- Can Someone Spot My Error

I m trying my hand at Euler Problem 4 in Haskell. It asks for that largest palindrome formed by multiplying two three-digit numbers. The problem was simple enough, and I thought my Haskell-fu was up ...

How does foldr work?

Can anybody explain how does foldr work? Take these examples: Prelude> foldr (-) 54 [10, 11] 53 Prelude> foldr (x y -> (x+y)/2) 54 [12, 4, 10, 6] 12.0 I am confused about these executions....

Efficient queue in Haskell

How can I efficiently implement a list data structure where I can have 2 views to the head and end of the list, that always point to a head a tail of a list without expensive calls to reverse. i.e: ...

Problem detecting cyclic numbers in Haskell

I am doing problem 61 at project Euler and came up with the following code (to test the case they give): p3 n = n*(n+1) `div` 2 p4 n = n*n p5 n = n*(3*n -1) `div` 2 p6 n = n*(2*n -1) p7 n = n*(5*n -3)...

Ways to get the middle of a list in Haskell?

I ve just started learning about Functional Programming, using Haskel. I m slowly getting through Erik Meijer s lectures on Channel 9 (I ve watched the first 4 so far) and in the 4th video Erik ...

haskell grouping problem

group :: Ord a => [(a, [b])] -> [(a, [b])] I want to look up all pairs that have the same fst, and merge them, by appending all the list of bs together where they have the same a and discarding ...

Closest equivalent to subprocess.communicate in Haskell

I want to do a popen() / python s subprocess.communicate from Haskell - start a program, give it stdin, and get its stdout/stderr. What s the most direct / Haskellish way to do this?