【问题标题】:Haskell - Why is Alternative implemented for ListHaskell - 为什么要为 List 实施替代方案
【发布时间】:2022-01-15 14:14:12
【问题描述】:

我已经阅读了这篇 Meaning of Alternative 的一些帖子(很长)

让我看到这篇文章的原因是总体上了解了 Alternative。这篇文章很好地回答了为什么它以 List 的方式实现。

我的问题是:

  • 为什么要为List 实现Alternative

是否有可能使用AlternativeList 的算法可能会传递给它,所以定义它以保持通用性?

我认为是因为Alternative 默认定义了somemany,这可能是其中的一部分,但What are some and many useful for 包含评论:

为了澄清,somemany 的定义对于最基本的类型,例如 []Maybe 只是循环。所以虽然somemany对它们的定义是有效的,但是没有任何意义。

在上面的“什么是一些有用的”链接中,Will 对可能包含我的问题的答案的 OP 给出了一个答案,但是在我的 Haskelling 中,森林有点厚,看不到树。

谢谢

【问题讨论】:

  • 为什么避免实施它?
  • @DanielWagner 我不知道该称您为智者还是老圣人,但这似乎表明了我对普遍性的看法。必须有一个首字母缩略词/在某处说不必要的乘法实现。谢谢!

标签: list haskell alternative-functor


【解决方案1】:

Haskell 库生态中有一个约定,如果一个事物可以是一个类的实例,那么它应该是一个类的实例。我怀疑“为什么是[]Alternative?”的诚实答案。是“因为它可以”。

...好吧,但是为什么存在这种约定呢?简短的回答是,实例是 Haskell 中只屈服于整个程序分析的一部分。它们是全局的,如果程序的两个部分都试图进行特定的类/类型配对,那么这种冲突会阻止程序正常工作。为了解决这个问题,有一条经验法则,即您编写的任何实例都应该与其关联的类或与其关联的类型存在于同一模块中。

由于实例应该存在于特定模块中,因此尽可能定义这些实例是礼貌的 - 因为另一个库尝试修复您没有提供实例的事实是不合理的。

【讨论】:

  • 太棒了!果然是老圣人。当我知道原因时我会更好,而您的回答比所提出的问题更深入地向我展示了原因。
  • 感谢您的解释。我想加入一些关于 Haskell 的哲学的东西,即实例应该尽可能存在,但我不知道为什么这是哲学。
  • 我同意,但我要说的是,这个约定仅适用于只有 one “合理”实例的情况。我的意思是,我们可以写instance Monoid Int,但是有很多方法可以做到,所以我们在库中没有这样的实例。我们有 Sum, Max, ... 几个选项的新类型包装器。
【解决方案2】:

在将[] 视为非确定性单子时,替代方案很有用。在这种情况下,<|> 代表两个程序之间的选择,empty 代表“没有有效的选择”。这与例如的解释相同。解析器。

somemany 确实对列表没有意义,因为它们会贪婪地从给定选项中迭代所有可能的元素列表,从第一个选项的无限列表开始。即使是这样,list monad 也不够懒惰,因为如果给它一个空列表,它可能总是需要中止。然而,当两者都终止时有一种情况:当给定一个空列表时。

Prelude Control.Applicative> many []
[[]]
Prelude Control.Applicative> some []
[]

如果 somemany 被定义为惰性(在正则表达式意义上),这意味着它们更喜欢短列表,你会得到结果,但不是很有用,因为它首先生成所有无限数量的列表只有第一个选项:

Prelude Control.Applicative> some' v = liftA2 (:) v (many' v); many' v = pure [] <|> some' v
Prelude Control.Applicative> take 100 . show $ (some' [1,2])
"[[1],[1,1],[1,1,1],[1,1,1,1],[1,1,1,1,1],[1,1,1,1,1,1],[1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,1,"

编辑:我相信somemany 函数对应于star-semiring,而&lt;|&gt;empty 对应于半环中的加号和零。所以在数学上(我认为),将这些操作拆分为一个单独的类型类是有意义的,但这也有点愚蠢,因为它们可以根据 Alternative 中的其他操作符来实现。

【讨论】:

    【解决方案3】:

    考虑这样的函数:

    fallback :: Alternative f => a -> (a -> f b) -> (a -> f e) -> f (Either e b)
    fallback x f g = (Right <$> f x) <|> (Left <$> g x)
    

    意义不大,但您可以想象它被用在解析器中:尝试一件事,如果不起作用,则退回到另一件事。

    这个函数在f ~ []时有意义吗?当然,为什么不呢。如果您将列表的“效果”视为在某个空间中的搜索,那么此功能似乎代表某种有偏见的选择,您更喜欢第一个选项而不是第二个选项,虽然您愿意尝试任何一个,但您也标记你去哪条路。

    像这样的函数是否可以成为某个算法的一部分,该算法在它计算的 Alternative 中是多态的?我不明白为什么不这样做。 [] 有一个 Alternative 实例似乎不是不合理的,因为有一个满足 Alternative 法律的实现。

    至于您指出的 Will Ness 链接的答案:它涵盖了 somemany 不要“只循环”列表。它们循环查找非空列表。对于空列表,它们会立即返回一个值。这有多大用处?可能不是很,我必须承认。但该功能与(&lt;|&gt;)empty 一起提供,可能很有用。

    【讨论】:

    • 澄清一下,this answer 真正讨论了[] 实例的manysome。 (也许这就是你的意思)。
    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2018-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    相关资源
    最近更新 更多