Can Higher Order Functions Be Pure in C++?

cfunctional programming

I was thinking about pure functions especially in the context of C++, which of course is not a purely functional language, and was wondering if higher order functions in C++ can ever be considered pure? Take for example std::find_if: it would be very pure except it takes another function, which might not be pure. There seems to be no constraint on the predicate std::find_if takes that prevents doing nasty, impure things inside the function, like this:

const std::vector<int> v = { 1,2,3,4,5 };
auto result = std::find_if(v.begin(), v.end(), [](int arg)
{
   return arg < someGlobalVariable;
} );

So maybe someone with more experience in functional programming languages could clarify this for me: Does the notion of 'pure functions' make sense when dealing with higher order functions?

EDIT: I should have stated more clearly that I am not looking for an explanation of const correctness in C++. I just wanted to know if the definition of a pure function makes sense when talking about higher order functions in C++. I changed the example to illustrate that const is not solving my problem here!

Best Answer

You're right, this is an issue when one wants to reason about purity of functions in a language that permits impure functions. Technically almost all languages allow impurity, but the purely functional ones usually explicitly mark the impure ones in the type system, such that the Haskell function map :: (a -> b) -> [a] -> [b] does, implicitly, require that the function to be mapped is pure.

Informally, we can certainly say: find_if is pure only if the predicate function is pure. So how might we teach the compiler about this?

Since C++ does not mark impure functions (nor pure ones, for that matter, but let's pretend we are adding that feature), and we probably don't want to restrict find_if to only accept pure functions (since that would be backwards incompatible), we are left with what I'll dub purity polymorphism. That is, find_if is pure iff the function passed in is pure. I'm not aware of a language doing this, but in principle it is no different from polymorphism over types (a.k.a. generics). Sufficently sophisticated effect systems probably have equivalent capability, just generalized to more and more fine-grained judgements than "pure" and "impure".