【问题标题】:Type Constraints in TypeclassTypeclass 中的类型约束
【发布时间】:2013-08-15 17:48:06
【问题描述】:

为了好玩,我正在构建一个解析器库。在这个库中,我有一个 Parser 数据类型:

data Parser e a = Parser (String -> Either e (a, String))

我能够定义ParserFunctorApplicative 实例,但我认为我不能在不限制“错误”类型或“值”类型的情况下创建Alternative 实例解析器可以返回。最初,当错误类型为 String 消息时,这使我创建了一个 Applicative 实例,但我意识到我应该能够将此约束释放到具有 Alternative 的任何消息数据类型(或者可能是 @987654330 @ 而不是?)实例也是如此。考虑到这一点,我写了这个:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
instance Alternative e => Alternative (Parser e)
  where
    empty = Parser $ \s -> Left empty
    (<|>) (Parser p1) (Parser p2) = Parser $ \s -> tryParser s p2 $ p1 s
      where
        tryParser s p2 (Left _ ) =  p2 s
        tryParser _ _ x          = x

很遗憾,编译失败。当我将它加载到 ghci 中时,我收到以下错误消息:

Parsertest.hs:31:47:
    Expecting one more argument to `e'
    In the instance declaration for `Alternative (Parser e)'
Failed, modules loaded: none.

当我在网上搜索时,这似乎是解决方案,但它对我不起作用。我错过了什么?

【问题讨论】:

    标签: haskell typeclass


    【解决方案1】:

    问题是Alternative 是用于类型构造函数* -&gt; *,所以如果你说

    instance Alternative e => ....
    

    那么e 必须是类型构造函数,而不是类型。所以e 可以是[]Maybe 之类的,但不是Int

    Alternative 的运算符是&lt;|&gt;,其类型为Alternative e =&gt; e a -&gt; e a -&gt; e a。这迫使e 接受一个参数来创建一个类型,就像Maybe 必须接受一个参数,例如Maybe Int

    使用Monoid 而不是Alternative,因为它是一个类型类而不是构造函数类。它的运算符 mappend 具有 Monoid e =&gt; e -&gt; e -&gt; e 类型,这是您想要组合错误的类型。

    【讨论】:

    • 这会让事情再次编译。你知道我在哪里可以读到 Monoid、Alternative、MonadPlus 什么时候可以使用吗?
    • Wellllll,我写了an answeranother 关于类似的主题 (here),如果你对那里的理论讨论感到满意的话。如果您在阅读它们后想要更实用的建议,您可以尝试将其作为一个新问题提出,但请注意明确表明您已阅读它们并且您需要指导何时选择它们,或者如果这是一个小的澄清其中一个答案,请在评论中提问。
    • @chanko 我应该说 Alternative is 适合解析器,而 Monoid 对错误类型有意义。
    • 是的,我知道如果我使用应用解析器,我应该保留 Alternative 实例。阅读这些链接让我考虑将我的解析器类型扩展为使用空解析器。这样,替代实例结构就不必依赖解析器本身的内部结构。感谢您提供有用的链接!
    • @chanko08 我认为&lt;|&gt; 应该回溯并在第一个解析器失败时使用第二个解析器。 (这是我用过的解析器所做的,它允许你用代码中的&lt;|&gt; 替换语法中的|。因此它应该查看输入——我认为解析器的内部是相关的。 Null 解析器更容易,但失败和回溯更有用。问题是如果没有 Wadler 的“如何用成功列表替换失败”方法,回溯很难。
    猜你喜欢
    • 2013-08-19
    • 1970-01-01
    • 2017-01-21
    • 2022-10-06
    • 2012-09-06
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多