Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 一种直观的箭头运算符应用思想_Haskell - Fatal编程技术网

Haskell 一种直观的箭头运算符应用思想

Haskell 一种直观的箭头运算符应用思想,haskell,Haskell,今天我花了几个小时的时间试图理解箭头操作符应用程序在Haskell中的作用。我现在正试图验证我的理解是否正确。简而言之,我发现对于arrow操作符 (f <*> g <*> h <*> v) z = f z (g z) (h z) (v z) (fghv)z=fz(gz)(hz)(vz) 在我继续之前,我意识到了这一点,但发现它非常复杂,比我今天希望得到的要复杂得多 为了理解applicative是什么,我从applicative在base中的箭头定义开

今天我花了几个小时的时间试图理解箭头操作符应用程序在Haskell中的作用。我现在正试图验证我的理解是否正确。简而言之,我发现对于arrow操作符

 (f <*> g <*> h <*> v) z = f z (g z) (h z) (v z)
(fghv)z=fz(gz)(hz)(vz)
在我继续之前,我意识到了这一点,但发现它非常复杂,比我今天希望得到的要复杂得多

为了理解applicative是什么,我从applicative在base中的箭头定义开始

instance Applicative ((->) a) where
    pure = const
    (<*>) f g x = f x (g x)
实例应用程序((->)a)其中
纯=常数
()fgx=fx(gx)
然后继续探究这些表达方式

(f <*> g <*> h) z
(f g h)z

(f g h v)z
膨胀时屈服

从定义上我们得到了

 f <*> g = \x -> f x (g x)
fg=\x->fx(gx)
由于
()
是左关联的,因此

 f <*> g <*> h = (f <*> g) <*> h
               = (\x -> f x (g x)) <*> h
               = \y -> (\x -> f x (g x)) y (h y)
fgh=(fg)h
=(\x->fx(gx))h
=\y->(\x->fx(gx))y(hy)
所以

 (f <*> g <*> h) z = (\y -> (\x -> f x (g x)) y (h y)) z
                   = (\x -> f x (g x)) z (h z)
                   = (f z (g z)) (h z)
                   = f z (g z) (h z)
(fghz=(\y->(\x->fx(gx))y(hy))z
=(\x->fx(gx))z(hz)
=(fz(gz))(hz)
=fz(gz)(hz)
最后一步是由于函数应用程序是左关联的。同样地

 (f <*> g <*> h <*> v) z = f z (g z) (h z) (v z)
(fghv)z=fz(gz)(hz)(vz)
对我来说,这为arrow应用程序的功能提供了一个非常清晰直观的概念但这是正确的吗?

为了测试我运行的结果,例如,下面

λ> ((\z g h v -> [z, g, h, v]) <*> (1+) <*> (2+) <*> (3+)) 4
[4,5,6,7]
λ>(\z g h v->[z,g,h,v])(1+(2+)(3+)4
[4,5,6,7]
这与上面得出的结果一致

在进行上面的扩展之前,我发现这个应用程序很难理解,因为它的使用会导致非常复杂的行为,因为咖喱。特别是

 (f <*> g <*> h <*> v) z = f z (g z) (h z) (v z)
(fghv)z=fz(gz)(hz)(vz)
函数可以返回其他函数。以下是一个例子:

λ> ((\z g -> g) <*> pure (++) <*> pure "foo" <*> pure "bar") undefined
"foobar"
λ>(\z g->g)纯(++)纯“foo”纯“bar”)未定义
“foobar”

在这种情况下,所有函数都会忽略
z=undefined
,因为
pure x z=x
,第一个函数通过构造忽略
z
。此外,第一个函数只接受两个参数,但返回一个接受两个参数的函数。

是的,您的计算是正确的。

在我看来是正确的。您的直觉完全正确。接下来,您应该处理
Monad
实例。在研究
(>)r
的实例时,您还可以获得其他应用程序和monad的有价值的直觉。谢谢大家!在注意到一种经验的理解方法失败得很惨之后,用纸和笔得出一个结果在数学上是非常有益的。当然,接下来是monad实例。用多余的括号写这篇文章可能会使它更清晰、更容易阅读,比如
(fghv)z=(fz)(gz)(hz)(vz)
。它也是
sequenceA[f,g,h,v]z=[fz,gz,hz,vz]
。通常,
实例应用程序((->)x),其中纯vx=v;(fg)x=(fx)$(gx)
也更容易阅读。威尔,我喜欢形式的对称性
(fz)(gz)(hz)(vz)
,但也喜欢
fz(gz)(hz)(vz)
仅仅是因为它显式地显示了提供给
f的有四个参数。
我要添加:
在函数applicative中是来自组合逻辑的S combinator:S f g e=f e(g e);它适用于f到g,其中每个人都可以访问“环境”e。
λ> ((\z g -> g) <*> pure (++) <*> pure "foo" <*> pure "bar") undefined
"foobar"