【发布时间】:2019-11-26 12:54:01
【问题描述】:
Conal Elliott's paper 有以下定义:
Future a = (Time, a)
Stepper :: a -> Event a -> Reactive a
Ev :: Future (Reactive a) -> Event a
never : Event a
instance Monad Reactive
rA :: Reactive String
rA = "IA" `Stepper` (Ev (1, "1A" `Stepper` never))
rB :: Reactive String
rB = "IB" `Stepper` (Ev (1, "1B" `Stepper` never))
rC1 :: Reactive String
rC1 = (++) <$> rA <*> rB
rC1 = "IAIB" `Stepper` (Ev (1, "IA1B" `Stepper` never))
我相信以上是正确的。
rC2 :: Reactive String
rC2 = rA >>= (\a -> (a++) <$> rB)
应该rC1 = rC2吗?
根据论文中的定义,"IA1B" and "1AIB" 似乎将包含在rC2 中的"IAIB" 和"1A1B" 之间。
这不违反单子定律(<*>) = ap 吗?不应该rC1 = rC2吗?或者我误解了什么。
【问题讨论】:
-
你认为这违反了哪条单子法则? monad 定律没有告诉我们任何关于
>>=和<*>之间关系的信息,只是关于单子操作的结构(只是>>=和return) -
@trpnd
(<*>) = apwhereap m1 m2 = m1 >>= (\x1 -> m2 >>= \x2 -> return (x1 x2)) -
@trpnd,它实际上在 iirc 文档中被列为 Applicative law,但我们通常确实需要 monad 和 Applicative 之间的一致性
-
从技术上讲,这更像是一种惯例而不是法律。尽管在违反它的情况下,预计在某种意义上这两个事物是等价的,即使不完全相同。例如,查看 haxl 之类的内容,其中
(<*>)可以并行运行,但ap不能。 -
看起来我们仍然应该只在
rC2中获得 2 个值,因为 monad 选择第一个到达的未来并丢弃另一个。你是如何计算rC2的?你能展示你的作品吗? (我没有一定怀疑你,我只需要查看更多细节并且我在手机上无法自己进行计算。)