f x y = 3 + y/x 点自由形式

f x y = 3 + y/x in point free form

我正在尝试找出 Haskell 中 f x y = 3 + y/x 的点自由形式。我以为会是 f = (3.0+) . flip (/),但答案是 f2 = curry $ (3.0+) . (uncurry $ flip (/)),这与 f1 = curry ((3.0+) . (uncurry (flip (/)))) 相同,例如我得到的答案是 uncurry before flip 和 curry 在开头。

我知道那个版本是如何工作的,但我不确定为什么需要 curry 和 uncurry 函数,以及为什么我的版本不起作用? (3.0+) 的类型是 a -> a,如果您通过函数组合将结果形式 flip (/) 提供给该函数,我认为它会起作用,但是 (3.0+) . flip (/) 2 10 会导致错误(为什么?)并且不会产生 8。uncurry 然后再 curry 不是多余的吗?

. 的类型签名是 (.) :: (b -> c) -> (a -> b) -> a -> c。如您所见,这仅在 second 函数(在您的回答 flip (/) 中)具有 一个参数 时有效。如果它有两个参数,我们可以使用 "owl operator" (.) . (.),其类型为:

(.) . (.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c

或者我们可以使用柯里化。通过在 flip (/) 部分使用 uncurry :: (a -> b -> c) -> (a, b) -> c,我们构造一个函数:

uncurry (flip (/)) :: Fractional c => (c, c) -> c

所以现在我们使用 单个 元组(因此是一个参数),然后我们再次使用 curry :: ((a, b) -> c) -> a -> b -> c 到 "unpack" 结果的第一个参数元组.

备选方案

如前所述,我们可以使用 owl 运算符:

   <b>((.) . (.))</b> (3.0+)  (flip (/))
-- ^   owl   ^

或者我们可以使用 owl 运算符的语法更复杂的版本:

((3 +) .) . flip (/)