我试图理解应用函子的交换法:
$this->params()->fromQuery('var_name');
令我困惑的是,函数应用程序u <*> pure y = pure ($ y) <*> u
,请考虑以下示例:
$ y
为什么第二个参数不应用于第一个?
答案 0 :(得分:6)
那是运算符部分。一些简单的例子:
Prelude> (/2) <$> [1..8]
[0.5,1.0,1.5,2.0,2.5,3.0,3.5,4.0]
Prelude> (:"!") <$> ['a'..'e']
["a!","b!","c!","d!","e!"]
(:"!")
部分是\c -> c:"!"
的语法糖,即它需要一个字符c
并将其添加到字符串"!"
。
同样,($ 2)
部分采用函数f
,只需将应用于数字2
。
请注意,这与普通的部分应用程序不同:
Prelude> ((/) 2) <$> [1..8]
[2.0,1.0,0.6666666666666666,0.5,0.4,0.3333333333333333,0.2857142857142857,0.25]
在这里,我只是将函数(/)
应用于一个固定参数2,即被除数。这也可以写成左侧部分 (2/)
。但是,正确的部分(/2)
会将2
应用为除数。
答案 1 :(得分:2)
您可以使用操作员部分执行此操作。例如:
(5+ ) -- Same as \ x -> 5+x
( +5) -- Same as \ x -> x+5
只有运营商才能实现这一目标;普通的命名函数只能从左到右进行曲解。
答案 2 :(得分:0)
Haskell备忘单运营商部分条目可以是:
(a `op` b) = (a `op`) b = (`op` b) a = (op) a b
当op
是实际运算符(不是字母数字名称)时,不需要反引号。
以上可以看作部分应用隐式定义的lambda表达式:
(a `op`) b = (a `op` b) = (\y -> a `op` y) b = (\x y -> x `op` y) a b = op a b
(`op` b) a = (a `op` b) = (\x -> x `op` b) a = (\y x -> x `op` y) b a = flip op b a
如果函数f
最终需要两个以上的参数,我们可以通过部分应用显式的lambda表达式来创建其curried版本:
(\y z x -> f x y z) b c -- = (\x -> f x b c)
(\x z y -> f x y z) a c -- = (\y -> f a y c)
(\x y z -> f x y z) a b -- = (\z -> f a b z)
最后一个案例仅相当于f a b
,第二个案例相当于(flip . f) a c
:
g b c a = f a b c = flip f b a c = flip (flip f b) c a = (flip . flip f) b c a
g a c b = f a b c = flip (f a) c b = (flip . f) a c b
g a b c = f a b c