Result
现在要修改一个一元函数的结果,可以这样实现:
result edit f x = edit (f x)
-- or
-- result edif f = edit . f
-- result = (.)
那么修改二元函数的最终结果呢?Haskell里的函数都被柯里化,可以看作一元函数,直接使用一次result
看看:
result2 edit f = result useEdit f
where useEdit = _
这里f
是个二元函数,userEdit
的参数应该是f
用一个参数部分调用后得到闭包,这又是一个一元函数,如果我们用result
修改闭包的结果,也就相当于修改原来二元函数的最终结果,所以:
result2 edit f = result useEdit f
where useEdit closure = result edit closure
再对这个result2
进行化简:
result2 edit f = result useEdit f
where useEdit closure = result edit closure
result2 edit f = result useEdit f
where useEdit = result edit
result2 edit f = result (result edit) f
result2 edit = result (result edit)
result2 edit = (result . result) edit
resul2 = result . result
同理,对n元函数的最后结果进行修改就是就是n个result的组合。只要result
能修改一元函数的结果,以及下面的等价关系,就很易懂了
f . g = \x -> f (g x)
Argument
现在我们要在调用一元函数前,修改它的参数:
arg :: (a -> b) -> (b -> c) -> a -> c
arg edit f x = f (edit x)
-- or
-- arg edif f x = (f . edit) x
-- arg = flip (.)
那么修改二元函数f
的第一个参数呢?在Haskell里函数都是一元的,所以用arg
就可以了。更有趣的是修改二元函数的第二个参数。要改第二个参数就要先部分调用f
得到一个闭包,然后再用arg
修改用闭包的第一个参数,所以可以组合result
和arg
arg2 = result . arg
同理,修改n元函数的最后一个参数就是 n - 1个result
和arg
的组合。
如果一个函数的类型是 (a -> b) -> (b -> c) -> c
,怎样用b -> b
的函数修改第一个参数的结果?
resultOfArg = arg . result
嗯,规律超明显。