Search code examples
haskellcurryingpointfree

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


I'm trying to figure out the point free form of f x y = 3 + y/x in Haskell. I thought it would be f = (3.0+) . flip (/), but the answer is f2 = curry $ (3.0+) . (uncurry $ flip (/)), which is the same as f1 = curry ((3.0+) . (uncurry (flip (/)))), e.g. the answer I got but with uncurry before flip and curry at the beginning.

I see how that version works, but I'm not sure why the curry and uncurry functions are needed, and why my version doesn't work? The type of (3.0+) is a -> a, which I thought would work if you fed that function with the result form flip (/) via function composition, but (3.0+) . flip (/) 2 10 results in an error (why?) and does not yield 8. Isn't it redundant to uncurry and then curry again?


Solution

  • The type signature of the . is (.) :: (b -> c) -> (a -> b) -> a -> c. As you can see, this only works if the second function (in your answer flip (/)) has one argument. In case it has two arguments, we can use the "owl operator" (.) . (.), which has type:

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

    Or we can use currying. By using uncurry :: (a -> b -> c) -> (a, b) -> c on the flip (/) part, we construct a function:

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

    so now we work with a single tuple (thus one argument), and then we use curry :: ((a, b) -> c) -> a -> b -> c to "unpack" the resulting first argument tuple again.

    Alternatives

    As discussed before, we can use the owl operator:

       ((.) . (.)) (3.0+)  (flip (/))
    -- ^   owl   ^

    Or we can use a syntactically more complex version of the owl operator:

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