f,g,h :: Kleisli((->)e)a b` <=>`f >>>(g &&& h)=(f >>> g)&&&(f >>> h)`?

时间:2019-08-13 03:07:54

标签: haskell monads arrows reader-monad kleisli

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

我试图更好地掌握Haskell中的Arrows,我想弄清楚

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

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

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的此语句,但没有找到{{1}的fgh这样的值}。这句话对f >>> (g &&& h) ≠ (f >>> g) &&& (f >>> h)确实适用吗?如果是,这是否可以证明这一点? f, g, h :: Kleisli ((->) e) a b的作用是从环境中读取。因此,应用Monad ((->) e)的结果是将要从环境中读取fg的功能。无论在何处创建此函数,它都是一样的,因为每次都将其应用于相同的参数,因此从环境中读取的结果是相同的,因此总体结果也相同。

1 个答案:

答案 0 :(得分:4)

直观地

是的,(->) e单子是阅读器单子,我们执行两次读取还是只执行一次读取都没有关系。一次运行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'))
相关问题