Gre*_*con 11
结构警察会注意到,这
De
是另一个不是monad的应用函子的例子 - join将把事物从遥远的未来带到不久的将来,而且最好不可能.然而,在一般情况下,应用仿函数只能穿过可穿越的仿函数(具有有限多个元素的容器),所以De
通过所有容器.所以它有点特别.我不知道它是什么.
和
的
De
算符表示固定的延迟,而不是任意的一个.我把时间分成不连续的切片.De x
是x
下一个切片的到期类型.De (De x)
因此是x
两片时间的到期类型,你不能让它更快出现!
阅读整篇文章.为了回答当前的问题,作者的结论是
别看!
好的,这是实施.这是骗局.
Run Code Online (Sandbox Code Playgroud)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))
I recently defined an Applicative instance for a newtype on top of (,,,)
, a "quad". (The standard library defines an instance for (,)
, but not (,,,)
. That's OK, as the standard implementation has different semantics than what I was after.)
背景是; 我正在解析一些旧数据,并且数据中的日期格式不明确.数据中的每个日期都可以解析为四种可能性,存储在四边形中.然后,我想验证四元组中的每个日期,以消除语义无效的日期.(有有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)
Run Code Online (Sandbox Code Playgroud)
一些先决条件"纯"功能:
parseDateInt :: Int -> DQ Date
validateDate :: Date -> Bool
extractBestDate :: DQ Date -> DQ Bool -> Date
Run Code Online (Sandbox Code Playgroud)
所以一旦我们得到解析日期的四元组(从parseDateInt
),我们需要验证它们:
validateDates :: DQ Date -> DQ Bool
validateDates = (validateDate <$>)
Run Code Online (Sandbox Code Playgroud)
(到目前为止,这只是一个Functor,但你也可以写
(pure validateDate <*>)
.
同样值得注意的是单个元素验证与验证集合中每个元素之间的对称性 - 验证一个元素,你可能会写
validateDate $ date
; 要写一套验证集
validateDate <$> dates
.这就是为什么fmap
写成<$>
,它是函数应用程序的函数.)
此后的步骤是获取一组有效的解析并将其折叠成最终结果:
intuitDateType :: [DQ Bool] -> DQ Bool
intuitDateType dates = foldl1 (liftA2 (&&)) dates
Run Code Online (Sandbox Code Playgroud)
所以现在您可以从[Int]
数据文件中转到DQ Bool
表示数据集的可能有效的日期表示.(并从那里,将每个数据点与实际日期对象相关联,而不是提供的片状Int.)
所以无论如何,这个职位已经变得有点长,但这个想法是一个应用型实例让我解决了约3行代码我的问题.我的问题域是重复将函数应用于容器中的数据,这是Applicative仿函数所做的.join
对这些数据没有任何操作,因此Monad实例没有多大意义.
Conal Elliott撰写有关信号处理器以及它们如何应用的文章.这些ZipList
在本质上是类似的,其中两个"容器"中的每个相应的一对物品被组合.
在我制作的一款未完成但又可爱的游戏中,我一直在使用这个概念(cabal install DefendTheKing
要查看它).
代码段/应用风格用法示例:
draw font
<$> lstP gABoard
<*> lstP gASelection
<*> mouseMotion
<*> lstP gASide
<*> lstP gAGameIteration
Run Code Online (Sandbox Code Playgroud)