f, g, h :: Kleisli ((->) e) a b <=> f >>> (g &&& h) = (f >>> g) &&& (f >>> h)?
f, g, h :: Kleisli ((->) e) a b <=> f >>> (g &&& h) = (f >>> g) &&& (f >>> h)?
编辑:如果存在这样的函数 f
,我们将称箭头 p
为纯箭头:p = arr f
.
我正在努力更好地掌握 Haskell 中的箭头,我想弄清楚什么时候
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
、g
和 h
这样的值 f >>> (g &&& h) ≠ (f >>> g) &&& (f >>> h)
。这个陈述对于 f, g, h :: Kleisli ((->) e) a b
是否确实如此,如果是这样,这是否可以有效证明:
Monad ((->) e)
的效果是从环境中读取。因此,应用 f
的结果是 g
和 h
将从环境中读取的函数。无论这个函数是在哪里创建的——都是一样的,因为它每次都应用于相同的参数,因此从环境中读取的结果是相同的,因此整体结果也是相同的。
凭直觉
是的,(->) e
monad 是一个 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'))
编辑:如果存在这样的函数 f
,我们将称箭头 p
为纯箭头:p = arr f
.
我正在努力更好地掌握 Haskell 中的箭头,我想弄清楚什么时候
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
、g
和 h
这样的值 f >>> (g &&& h) ≠ (f >>> g) &&& (f >>> h)
。这个陈述对于 f, g, h :: Kleisli ((->) e) a b
是否确实如此,如果是这样,这是否可以有效证明:
Monad ((->) e)
的效果是从环境中读取。因此,应用 f
的结果是 g
和 h
将从环境中读取的函数。无论这个函数是在哪里创建的——都是一样的,因为它每次都应用于相同的参数,因此从环境中读取的结果是相同的,因此整体结果也是相同的。
凭直觉
是的,(->) e
monad 是一个 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'))