如何组合具有两个参数的函数?

How to compose functions with two argumens?

我知道我能做到:

fn1 :: B -> C

fn2 :: (A -> B) -> (A -> C)
fn2 callback = callback >>> fn2

但是我如何编写 (>>>) 一个有两个参数的函数?:

fn3 :: (Z -> A -> B) -> (Z -> A -> C)
fn3 callback = callback (\z a -> fn1 z a # fn2) ✅

fn3' :: (Z -> A -> B) -> (Z -> A -> C)
fn3' callback = callback (???) fn2 -- >>> won't work 

??? 运算符应该是什么 return 与 >>> 完全一样,但在 运行 [=18= 之前采用 fn1 所需的附加参数] 因为 >>> 行不通?

更具体

我正在尝试更优雅地 FFI 这个功能

const functions = require("firebase-functions");

exports.onRequestImp = function (handler) {
  return functions.https.onRequest((request, response) => {
    handler(request)(response)();
  });
}
module Firebase.Functions.HTTP (onRequest) where

import Prelude

import Control.Promise (Promise, fromAff)
import Effect (Effect)
import Effect.Aff (Aff)
import Node.Express.Types (Request, Response)

foreign import onRequestImp :: (Request -> Response -> Effect (Promise (Unit))) -> Effect Unit

onRequest :: (Request -> Response -> Aff (Unit)) -> Effect Unit
onRequest handler = do
  onRequestImp
    ( \req res -> do
        handler req res # fromAff
    )

首先,您的类型签名似乎有偏差。在您的第一个代码块中,根据您提供的 fn3 定义,它应该如下所示:

fn3 :: A -> C
fn3 = fn1 >>> fn2

同样,如果我没看错题意,在第二个代码块中,组合类型应该是:

fn3 :: A -> B -> D

也就是说,您将 fn1 的输出作为 fn2 的输入。


说完这些,我们来谈谈构图。答案是:是也不是。

不,标准库中没有这样的组合operator/function,因为它通常没有用。像这样组合函数会严重掩盖正在发生的事情,并使您的程序更难维护。

但是,是的,在库中定义了这样的组合 operator/function,专门用于编写无点程序 - compose2 and its friend compose2Flipped,别名为运算符形式 <....> 分别为:

import PointFree ((..>))

fn1 :: A -> B -> C
fn2 :: C -> D

fn4 :: A -> B -> D
fn4 = fn1 ..> fn2

话虽如此,我强烈建议不要使用这样的构图。无点表示法简洁而酷,但在实践中它只会让你的程序难以理解。最好直接写出你的意思:

fn4 :: A -> B -> D
fn4 a b = fn2 (fn1 a b)

P.S。这是一个巧妙的技巧:你认为我是如何找到那个图书馆的?我又不是把所有的库和它们的类型和函数都记住了,对吧?

我使用了 Pursuit 搜索。我知道您要查找的函数的类型签名是 (a -> b -> c) -> (c -> d) -> (a -> b -> d),我只是将其插入到搜索中,瞧!

在这里,自己尝试一下:https://pursuit.purescript.org/search?q=(a+-%3E+b+-%3E+c)+-%3E+(c+-%3E+d)+-%3E+(a+-%3E+b+-%3E+d)