在类型签名中反映对象内部

Reflecting object internals in type signature

我正在研究 JS 中的 FP(我是 FP 的新手),我遇到了一些 "problem" 描述柯里化函数的剩余参数,包装到 Functors

假设我们有以下 curried 情况:

const makeApiCallFuture = curry((path, user, password, params) => Future(...));
const makeApiCallIoFuture = (path) => IO(makeApiCallFuture(path));

// And so on, let's imagine that each next function reduces one more arg
const someFunc = compose(ap(userIO), makeApiCallIoFuture);

我想为每个函数指出它仍然需要多少柯里化参数,即使这些函数包装在 Functor 中,以避免在开发中出现任何混淆。

比如makeApiCallFuture我们可以写成String -> String -> String -> Object -> Future就很清楚了

下一个函数 makeApiCallIoFuture 减少了柯里化参数的数量并将函数的其余部分包装到 IO 中。

类型签名变为 makeApiCallIoFuture :: String -> IO 甚至 makeApiCallIoFuture :: String -> IO a 我认为这还不够清楚,因为 IO 中的函数仍然是柯里化的,开发人员需要深入研究代码以了解有多少他们仍然需要通过参数。

所以,我的问题是 - 是否可以使用类型签名来指示此类情况?也许可以这样写:

makeApiCallIoFuture :: String -> IO (String -> String -> Object -> Future)

someFunc :: String -> IO (String -> Object -> Future)

甚至更冗长:

makeApiCallIoFuture :: Path -> IO (User -> Password -> Params -> Future)
    User = String
    Password = String
    Params = Object

someFunc :: User -> IO (Password -> Params -> Future)
    User = String
    Password = String
    Params = Object

The type signature becomes makeApiCallIoFuture :: String -> IO

没有。 IO 需要一个类型参数,单独它是一个无效的(或:不完整的)类型。

or maybe even makeApiCallIoFuture :: String -> IO a which is I think not clear enough

什么是a?您的 makeApiCallIoFuture 不是通用的 a,因此未指定 a 类型是错误的。

is it possible to indicate such situations using the type signatures? Maybe it's possible to write something like:

makeApiCallIoFuture :: String -> IO (String -> String -> Object -> Future)

是的,这是唯一正确的解决方案。