In Haskell, ignoring certain annoyances like bottom, we have a Cartesian closed category, or CCC, of types and functions. In CCCs, there are function types and Cartesian product types and they are related by the curry and uncurry isomorphisms (named after Haskell Curry).

curry :: ((a , b) -> c) -> (a -> b -> c)

uncurry :: (a -> b -> c) -> ((a , b) -> c)

But CCCs have another important property, they are endowed with a “terminal object”, that is an object t such that there is a unique function f :: a -> t for any a. In Haskell, the terminal object is (), called unit, and it has only one value, also (), and hence only one (polymorphic) function to it, the constant function \ x -> (). If you think about Cartesian products with any number n of factors (a1 , a2 , .. , an), you can think of () as the special case with 0 factors. And just like we can generalize currying to functions with any number n > 2 of arguments, we can think about “zurrying” functions with 0 arguments.

zurry :: (() -> a) -> a

unzurry :: a -> (() -> a)

zurry f = f ()

unzurry x = \ () -> x

What does that give us? Well, nothing, but it lets us recognize that function evaluation is really just a zurried form of function composition.

unzurry (f x) = f . (unzurry x)

So function evaluation isn’t really first class, and since this is Functional Programming, maybe we should think of everything as a function, by unzurrying if necessary!

P.S. When working with a monad, you work in its Kleisli category which is another example of a CCC. The above discussion relating function evaluation to function composition, would then relate Kleisli evaluation (>>=) to Kleisli composition (>=>).