5

p编辑:如果存在这样的函数,我们将调用纯箭头fp = arr f.

我正在尝试更好地掌握 Haskell 中的 Arrows,我想知道什么时候

f >>> (g &&& h) = (f >>> g) &&& (f >>> h), f, g,h是箭头。

显然,这通常不是真的。在此特定示例中,副作用在右侧重复:

GHCi> c = Kleisli $ \x -> ("AB", x + 1)
GHCi> fst . runKleisli (c >>> c &&& c) $ 1
"ABABAB"
GHCi> fst . runKleisli ((c >>> c) &&& (c >>> c)) $ 1
"ABABABAB"

显然,f >>> (g &&& h) = (f >>> g) &&& (f >>> h)如果f是纯粹的。

我在 GHCi 中用这个语句进行试验f, g, h :: Kleisli ((->) e) a b,并没有设法找到f,ghthat的值f >>> (g &&& h) ≠ (f >>> g) &&& (f >>> h)。这个陈述对于 真的是真的吗f, g, h :: Kleisli ((->) e) a b,如果是的话,这是否是一个有效的证明: 的效果Monad ((->) e)是从环境中读取。因此,应用的结果f是函数将借助该函数从环境中读取gh无论这个函数是在哪里创建的——都是一样的,因为它每次都应用于同一个参数,因此从环境中读取的结果是相同的,因此整体结果也是一样的。

4

1 回答 1

4

直观地

是的,(->) emonad 是一个 reader monad,我们执行两次读取还是只执行一次都没有关系。运行f一次或两次并不重要,因为它总是会产生相同的结果,具有相同的效果(读取)。

你的推理在我看来直觉上是正确的。

正式地

f, g, h :: Kleisli ((->) e) a b本质上意味着f, g, h :: a -> (e -> b),移除包装。

同样,忽略包装,我们得到

for all (f :: a -> e -> b) and (g :: b -> e -> c)
f >>> g = (\xa xe -> g (f xa xe) xe)

for all (f :: a -> e -> b) and (g :: a -> e -> c)
f &&& g = (\xa xe -> (f xa xe, g xa xe))

因此:

f >>> (g &&& h)
= { def &&& }
f >>> (\xa xe -> (g xa xe, h xa xe))
= { def  >>> }
(\xa' xe' -> (\xa xe -> (g xa xe, h xa xe)) (f xa' xe') xe')
= { beta }
(\xa' xe' -> (g (f xa' xe') xe', h (f xa' xe') xe'))


(f >>> g) &&& (f >>> h)
= { def >>> }
(\xa xe -> g (f xa xe) xe) &&& (\xa xe -> h (f xa xe) xe)
= { def &&& }
(\xa' xe' -> ((\xa xe -> g (f xa xe) xe) xa' xe', (\xa xe -> h (f xa xe) xe) xa' xe'))
= { beta }
(\xa' xe' -> (g (f xa' xe') xe', h (f xa' xe') xe'))
于 2019-08-13T07:21:42.763 回答