Q:

takeWhile, groupBy and group higher order functions

I'm trying to implement few higher order functions from Haskell in C++. Below are the definitions of takeWhile, groupBy, and group.
I would appreciate it if someone can review and comment if the implementation takes care of all scenarios. Should I be using universal refs for parameters to these functions? Please let me know of any other comments, too. Please assume C++14 standard and above. Also, if there are existing implementations that I can use to study and refer to, please point me to them too.
#include <vector>
#include <utility>

template <typename fwd_iter, typename predicate>
auto takeWhile(fwd_iter first, fwd_iter last, predicate p) -> std::pair<fwd_iter, fwd_iter>
{
    auto till = (first);

    for (; till != last; till++) {
        if (!p(*till)) {
            break;
        }
    }

    return { first, till };
}

// something similar to std::greater or std::less.. is there something for equality??
struct equal {
    template <typename T>
    constexpr bool operator()(const T &lhs, const T &rhs) const
    {
        return lhs == rhs;
    }
};

// predicate type should be : typename *fwd_iter -> typename *fwd_iter  -> bool) 
template <typename fwd_iter, typename predicate, 
    typename container = std::vector<std::pair<fwd_iter, fwd_iter>>>
auto groupBy(fwd_iter first, fwd_iter last, predicate pred)
{
    auto current = first;
    container ret;

    while (current != last) {
        auto t = takeWhile(current, last, [&](auto x) {return pred(*current, x); });
        current = t.second;
        ret.emplace_back(t);
    }

    return ret;
}

template <typename fwd_iter>
auto group (fwd_iter first, fwd_iter last)
{
    return groupBy(first, last, equal());
}

A:

struct equal is kind of useless. There's std::equal_to, which does the same thing.
You can make the design more flexible (and more standard library-like) by passing an output iterator to the groupBy and group function instead of creating a new container inside the function. It's useful if the user wants to write pairs that represent groups to an existing container or to a C-style array. 

