【问题标题】:Applicative functors other than monads and ZipList?单子和 ZipList 以外的应用函子?
【发布时间】:2011-01-08 09:30:04
【问题描述】:

应用程序的两个著名示例是 monad 和 ziplist。还有其他例子吗?

【问题讨论】:

    标签: haskell functional-programming


    【解决方案1】:

    来自Time flies like an applicative functor,Conor McBride:

    结构警察会注意到De 是应用函子的另一个例子,它不是一个 monad——join 会将事情从遥远的未来带到不远的未来,而这最好是不可能的。然而,应用函子通常只通过可遍历函子(具有有限多个元素的容器),De 会通过所有容器。所以有点特别。我想知道它是什么。

    De 函子表示固定延迟,而不是任意延迟。我把时间分成离散的片断。 De x 是在下一个切片到期的 x 的类型。因此,De (De x)x 的类型,在两片时间内到期,你不能让它早点出现!

    阅读整篇文章。为了回答直接的问题,作者的结论是

    别看!

    好的,这是实现。这是一个骗局。

    newtype De x = De x deriving Show -- ssh, don't tell!
    
    instance Functor De where
      fmap f (De x) = De (f x)
    
    instance Applicative De where
      pure = De
      De f <*> De s = De (f s)
    
    fix :: (De x -> x) -> x
    fix f = f (De (fix f))
    

    【讨论】:

      【解决方案2】:

      我最近在(,,,) 之上为一个新类型定义了一个Applicative 实例,一个“quad”。 (标准库为(,) 定义了一个实例,但不是(,,,)。没关系,因为标准实现的语义与我所追求的不同。)

      背景是;我正在解析一些旧数据,数据中的日期格式不明确。数据中的每个日期都可以解析为四种可能性,存储在四边形中。然后我想验证四边形中的每个日期以消除语义上无效的日期。 (没有 32 天的月份,没有 34 个月,没有第 5 季度等)最后,我想取数据集中的每个日期,并将整个集合缩减为一个四边形,表示哪些日期格式是有效的对于整个集合。然后,我从这些选项中选择最佳格式,并假设这就是数据集的日期格式。

      整个操作很容易表达为四边形结构上的应用操作。

      这是代码的基本形状:

      我的新类型:

      newtype DQ a = DQ (a, a, a, a) -- date quad
                   deriving ...
      
      instance Functor DQ where
         g `fmap` f = pure g <*> f
      
      instance Applicative DQ where
         pure x  = DQ (x, x, x, x)
         DQ (g, h, i, j) <*> DQ (a, b, c, d) = DQ (g a, h b, i c, j d)
      

      一些先决条件“纯”功能:

      parseDateInt :: Int -> DQ Date
      validateDate :: Date -> Bool
      extractBestDate :: DQ Date -> DQ Bool -> Date
      

      因此,一旦我们获得了已解析日期的四边形(来自 parseDateInt),我们需要验证它们:

      validateDates :: DQ Date -> DQ Bool
      validateDates = (validateDate <$>)
      

      (到目前为止,这只是一个 Functor,但你也可以写 (pure validateDate &lt;*&gt;).

      还值得注意的是单个验证之间的对称性 元素,并验证集合中的每个元素——为了验证一个元素,你可以写 validateDate $ date;为了验证一个集合,你写 validateDate &lt;$&gt; dates。这就是为什么fmap 写成&lt;$&gt;,它是函子的函数应用。)

      这之后的步骤是获取一组有效的解析并将其折叠 最终结果:

      intuitDateType :: [DQ Bool] -> DQ Bool
      intuitDateType dates = foldl1 (liftA2 (&&)) dates
      

      所以现在您可以从数据文件中的[Int] 转到DQ Bool 表示数据集的可能有效的日期表示。 (然后从那里,将每个数据点与一个真实的日期对象相关联, 而不是提供的片状 Int。)

      所以无论如何,这篇文章有点长,但我的想法是 应用实例允许我用大约 3 行来解决我的问题 的代码。我的问题域是反复将函数应用于数据 容器,这是 Applicative 函子所做的。该数据没有join 操作,因此Monad 实例没有多大意义。

      【讨论】:

      • 实际上这确实来自一个monad,带有join ((a, _, _, _), (_, b, _, _), (_, _, c, _), (_, _, _, d)) = (a, b, c, d)(直到newtypes)。它与Reader T monad 同构(可能只忽略_|_s),其中T 是具有四个值的类型。
      【解决方案3】:

      Conal Elliott writes about signal processors and how they're applicatives。它们在本质上类似于ZipList,其中两个“容器”中的每一对项目都被组合在一起。

      我在我制作的一个未完成但很可爱的游戏中经常使用这个概念(cabal install DefendTheKing 来看看)。

      代码 sn-p/Applicative 样式用法示例:

      draw font
      <$> lstP gABoard
      <*> lstP gASelection
      <*> mouseMotion
      <*> lstP gASide
      <*> lstP gAGameIteration
      

      【讨论】:

      • @djv:我可以,但是这样做需要关于其余代码的大量上下文,所以我不能做一个简短的解释。我打算完成我的游戏,然后也许很快就会写一篇关于它的博客文章。到那时,我希望我的代码(带有上下文)有点不言自明。欢呼
      【解决方案4】:

      Formlets 是对 HTML 表单的抽象,以组合应用程序的形式描述。 formlet 应用程序是由名称生成应用程序(生成表单元素名称)、XML 编写器应用程序(生成 HTML)和环境应用程序(提供提交的表单值)组成的结果。

      Formlets 可以通过组合额外的应用程序来扩展,例如实现验证。

      Cooper、Wadler 等人在论文中表明,formlets 不能表示为 monad。

      Formlets 已在 Haskell 中实现,here is the package

      【讨论】:

        【解决方案5】:

        Swierstra 和 Duponcheel 定义了一种高效的解析器风格,这种解析器几乎是 Arrows 的早期典型代表,但它不需要 Arrows 提供的任何 Applicative 无法提供的东西。但是,当时还没有创造出 Applicatives。

        它有效地为 LL(1) 解析器计算“FIRST”集,并使用它来进行更智能的分支选择。但是,当您以单子方式工作时,您无法计算这些集合。

        这可能不是一个非常公平的例子,因为 Swierstra/Duponcheel 解析器承认静态和动态解析器​​的混合,并且只有静态解析器被限制为适用性。

        通过可观察共享,您可以将他们的解析器设计推得更远,还可以计算“FOLLOW”集(只要您注意不要构建无限上下文无关语法。)。这为解析上下文无关语法提供了很好的渐近保证,而在使用单子(上下文敏感)解析器设计进行解析时,您将无法使用这些语法。

        也许同样有趣的是,考虑应用的 可用的结构,但不是纯的。许多comonads承认类似()的定义,它尊重comonads的结构,但对“纯”没有合理的定义。我的 semigroupoids 包和依赖它的无数包进一步探索了这个想法。

        【讨论】:

          【解决方案6】:

          我相信箭头是应用函子。 Control.Applicative 中肯定有 WrapArrow 类型。

          【讨论】:

            【解决方案7】:

            McBride 和 Paterson http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf 表明可以将幺半群视为应用函子,但一般情况下它不是单子。

            【讨论】:

              猜你喜欢
              • 2017-05-15
              • 1970-01-01
              • 2014-07-18
              • 2012-02-24
              • 1970-01-01
              • 2013-12-20
              • 1970-01-01
              • 2014-10-05
              • 1970-01-01
              相关资源
              最近更新 更多