如何对双参数函数使用类似>>>的运算符完成函数组合
问题解答
你要实现的是对多参数函数的返回值做后续变换,对应你描述的和>>>效果一致的组合能力,有两种常用实现方案:
1. 直接使用嵌套map(无需自定义运算符,兼容性最好)
函数本身就是Functor的实例,对接受n个参数的函数做返回值变换,只需要嵌套n层map即可。
你给出的双参数场景下,只需要两层map就能完全替代你写的lambda:
fn3' :: (Z -> A -> B) -> (B -> C) -> (Z -> A -> C) fn3' callback transform = map (map transform) callback
对应到你的具体FFI绑定场景,onRequest可以直接简化为:
onRequest :: (Request -> Response -> Aff (Unit)) -> Effect Unit onRequest handler = onRequestImp (map (map fromAff) handler)
如果你偏好正向组合运算符>>>,也可以写成等价形式:
onRequest handler = onRequestImp (handler >>> map (>>> fromAff))
2. 自定义多参数组合运算符
如果觉得嵌套map写起来麻烦,你可以自定义专门给双参数函数用的组合运算符,社区里通常把这种组合符叫“猫头鹰运算符”,对应>>>风格的正向版本定义如下:
-- 双参数函数正向组合运算符,参数顺序和>>>保持一致 (>>>>) :: forall z a b c. (z -> a -> b) -> (b -> c) -> (z -> a -> c) f >>>> g = \z a -> f z a >>> g -- 等价于 f >>>> g = map (map g) f -- 也等价于 (>>>>) = (>>>) . (>>>)
定义后你就可以直接按你期望的写法使用:
fn3' callback = callback >>>> fn1
对应FFI场景也可以写成:
onRequest handler = onRequestImp (handler >>>> fromAff)
额外说明
如果后续你需要处理3参数函数,只需要嵌套3层map,或者再定义3参数版本的组合符(>>>>>) = (>>>) . (>>>) . (>>>)即可,逻辑是完全统一的。这种写法本质是利用了函数函子的性质:对函数a -> b做map f等价于\x -> f (apply x),每多一层参数就多套一层map即可。
内容的提问来源于stack exchange,提问作者Coding Edgar
相关产品推荐
相关产品推荐

