I will give two slightly indirect answers.
First, consider the following code:
module Lambda where derivApprox fhx = ( (f (x + h)) - (fx) ) / h
I compiled this by telling the GHC to dump the intermediate view, which is a roughly simplified version of Haskell, used as part of the compilation process to get the following:
Lambda.derivApprox :: forall a. GHC.Real.Fractional a => (a -> a) -> a -> a -> a [LclIdX] Lambda.derivApprox = \ (@ a) ($dFractional :: GHC.Real.Fractional a) -> let { $dNum :: GHC.Num.Num a [LclId] $dNum = GHC.Real.$p1Fractional @ a $dFractional } in \ (f :: a -> a) (h :: a) (x :: a) -> GHC.Real./ @ a $dFractional (GHC.Num.- @ a $dNum (f (GHC.Num.+ @ a $dNum xh)) (fx)) h
If you look past dirty annotations and verbosity, you should see that the compiler turned everything into lambda expressions. We can take this as an indication that you probably don't need to do this manually.
Conversely, consider a situation in which you may need lambdas. Here's a function that uses a fold to compile a list of functions:
composeAll :: [a -> a] -> a -> a composeAll = foldr (.) id
What is it? Not a lambda in sight! In fact, we can go the other way:
composeAll' :: [a -> a] -> a -> a composeAll' xs x = foldr (\fgx -> f (gx)) id xs x
This is not only a full lambdas, but also two arguments for the main function and, moreover, the use of foldr for all of them. Compare the type of foldr , (a -> b -> b) -> b -> [a] -> b with the above; apparently these are three arguments, but above we applied it to four! Not to mention that the battery function takes two arguments, but there are three lambda arguments here. The trick, of course, is that both return a function that takes one argument; and we just apply this argument in place, instead of juggling lambdas around.
All that, I hope, convinced you that these two forms are equivalent. Lambda forms are never needed, or perhaps always necessary, because who can tell the difference?