两个众所周知的应用实例是monad和ziplists。还有其他例子吗?
答案 0 :(得分:11)
来自Conor McBride的Time flies like an applicative functor:
结构警察会注意到
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))
答案 1 :(得分:9)
我最近在(,,,)
之上定义了一个新类型的Applicative实例,一个“四元组”。 (标准库定义了(,)
的实例,但不是(,,,)
。这没关系,因为标准实现的语义与我之后的语义不同。)
背景是;我正在解析一些旧数据,并且数据中的日期格式不明确。数据中的每个日期都可以解析为四种可能性,存储在四边形中。然后,我想验证四元组中的每个日期,以消除语义无效的日期。 (没有月份有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 <*>)
。
值得注意的是单个验证之间的对称性
元素,并验证集合中的每个元素 - 验证一个,你可能会写
validateDate $ date
;要写一套验证集
validateDate <$> dates
。这就是fmap
被写为<$>
的原因,它是函数应用程序的一个函数。)
此后的步骤是采取一组有效的解析并折叠它 最后的结果:
intuitDateType :: [DQ Bool] -> DQ Bool
intuitDateType dates = foldl1 (liftA2 (&&)) dates
现在您可以从数据文件中的[Int]
转到DQ Bool
表示数据集的可能有效的日期表示。
(并从那里,将每个数据点与实际日期对象相关联,
而不是提供的片状Int。)
所以无论如何,这篇文章已经有点长了,但是这个想法是一个
应用实例允许我在大约3行中解决我的问题
代码我的问题域是重复将函数应用于数据
容器,这是一个Applicative仿函数。对这些数据没有join
操作,因此Monad实例没有多大意义。
答案 2 :(得分:5)
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
答案 3 :(得分:4)
Formlets是对构成应用程序的HTML表单的抽象。 formlet applicative是组合生成applicative的名称(生成表单元素名称),XML编写器应用程序(生成HTML)和环境应用程序(提供提交的表单值)的结果。
可以通过编写其他应用程序来扩展Formlet,例如实现验证。
Cooper,Wadler等人在论文中表明,小分析不能表示为monad。
在Haskell中实现了Formlets,here is the package。
答案 4 :(得分:4)
Swierstra和Duponcheel定义了一种高效的解析器样式,这个解析器几乎是Arrows的早期版本,但是它不需要来自Arrow的任何东西,它无法从Applicative获得。但是,申请人当时并没有被创造出来。
实际上,它为LL(1)解析器计算'FIRST'集,并使用它来进行更智能的分支选择。但是,当您单独工作时,无法计算这些集。
这可能不是一个非常公平的例子,因为Swierstra / Duponcheel解析器允许混合使用静态和动态解析器,并且只有静态解析器才限于应用。
通过可观察共享,您可以进一步进行解析器设计并计算“FOLLOW”集(只要您小心不构建无限上下文无关语法。)。这为解析上下文无关语法提供了很好的渐近保证,在使用monadic(上下文敏感)解析器设计进行语法分析时,这些语法是不可用的。
也许有趣的是,要考虑&lt; *&gt;的结构。适用的是,但不是纯粹的。许多comonads承认一个(&lt; *&gt;)类似的定义,它尊重comonad的结构,但对'pure'没有合理的定义。我的semigroupoids包和依赖它的无数包进一步探索了这个想法。答案 5 :(得分:1)
我相信箭是适用的算符。在Control.Applicative中肯定有一个WrapArrow类型。
答案 6 :(得分:1)
McBride和Paterson http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf表明,monoid可以被视为一个应用函子,但一般情况下它不是monad。