代码之家  ›  专栏  ›  技术社区  ›  sdcvvc

除了单子和ziplist之外的应用函子?

  •  14
  • sdcvvc  · 技术社区  · 14 年前

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

    7 回复  |  直到 11 年前
        1
  •  11
  •   Greg Bacon    11 年前

    Time flies like an applicative functor 康纳·麦克布莱德:

    结构警察会注意到 De 另一个例子是一个应用函子,它不是monad'join,它将把事物从遥远的未来带到不久的将来,而这最好是不可能的。然而,在一般情况下,应用函子只能穿过可遍历函子(包含有限多个元素的容器)的情况下, 扩散系数 拉过所有容器。所以有点特别。我想知道是什么。

    这个 扩散系数 函子表示固定的延迟,而不是任意的延迟。我把时间分成几段。 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
  •  9
  •   jrockway    14 年前

    我最近在 (,,,) ,一个“四边形”。(标准库为 (,) ,但不是 (,,,) . 没关系,因为标准实现的语义与我之前的不同。)

    背景是;我正在解析一些旧数据,数据中的日期格式不明确。数据中的每个日期都可以解析为四种可能,存储在四元表中。然后我想验证四元中的每个日期,以消除语义上无效的日期。(没有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 <$>)
    

    (到目前为止这只是一个函子,但你也可以写 (pure validateDate <*>) .

    同样值得注意的是,一个 元素,并验证集合中的每个元素——若要验证一个元素,可以编写 validateDate $ date ;要验证集合,请编写 validateDate <$> dates . 这就是为什么 fmap 写为 <$> ,这是函子的函数应用。)

    接下来的步骤是进行一组有效的解析并折叠 最终结果:

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

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

    所以不管怎样,这篇文章有点长,但是我的想法是 应用实例允许我用大约3行代码来解决问题 代码的。我的问题域在 容器,这就是应用函子所做的。没有 join 对该数据执行操作,因此monad实例没有多大意义。

        3
  •  5
  •   Conal    12 年前

    Conal Elliott writes about signal processors and how they're applicatives . 类似于 ZipList 在自然界中,两个“容器”中的每一对项目都被组合在一起。

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

    应用程序样式用法的代码段/示例:

    draw font
    <$> lstP gABoard
    <*> lstP gASelection
    <*> mouseMotion
    <*> lstP gASide
    <*> lstP gAGameIteration
    
        4
  •  4
  •   Mauricio Scheffer    14 年前

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

    可以通过组合其他应用程序来扩展formlet,例如实现验证。

    库珀、瓦德勒等人在论文中指出,形式不能表示为单子。

    表单已经在haskell中实现了, here is the package .

        5
  •  4
  •   Edward Kmett    12 年前

    swierstra和duponcheel定义了一种高效的解析器样式,这个解析器几乎是arrows的早期海报子代,但是它不需要arrow中的任何东西,它不能从applicative中获得这些东西。然而,当时还没有发明应用程序。

    它有效地为ll(1)解析器计算“first”集,并使用它进行更智能的分支选择。然而,你不能计算这些集合时,你的工作单。

    这可能不是一个非常公平的例子,因为swierstra/duponcheel解析器允许静态和动态解析器的混合,而且它只是一个仅限于应用的静态解析器。

    有了Observable sharing,您可以进一步进行解析器设计,还可以计算“follow”集(只要您小心不要构建无限上下文无关语法)。这为解析上下文无关文法提供了很好的渐近保证,在使用一元(上下文敏感)解析器设计进行解析时,这些保证是不可用的。

    同样有趣的是,考虑applicative的<*>可用的结构,而不是纯结构。许多comonad承认类似于(<*>)的定义,它尊重comonad的结构,但是没有一个合理的定义来定义“pure”。我的半群体包和无数依赖它的包进一步探索了这个想法。

        6
  •  1
  •   Paul Johnson    14 年前

    我相信箭是有用的函子。control.applicative中当然有wraparow类型。

        7
  •  1
  •   Vlad Patryshev    12 年前

    麦克布莱德和帕特森 http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf 证明一个幺半群可以被当作一个应用函子,但一般情况下它不是一个单子。