Support for arrays in `startsWith` (and, maybe, `endsWith`)

**Use case**

Would be quite useful for handling tree-like structured data where the node paths are specified as arrays of names or IDs.

**Describe the solution you'd like**

The desired behavior would be like this:
```
startsWith([1, 2, 3, 4], [1, 2])  -- true (1)
startsWith(['qwe', 'rty', 'ui', 'op'], ['qwe', 'rty'])  -- true (1)
startsWith([1, 2, 3, 4], [2, 4])  -- false (0)
startsWith([1, 1, 2, 2], [1, 2])  -- false (0)
```

And similarly, for `endsWith`

**Describe alternatives you've considered**

Something like `arraySlice(first, 1, length(second)) = second`

But `startsWith` would be much more readable, harder to make a mistake in and, probably, can be better optimized (i.e. might not have to create new objects like `arraySlice` does)
{
    if constexpr (search_type == ArraySearchType::Substr)
        return sliceHasImplSubstr<FirstSliceType, SecondSliceType, isEqual, isEqualSecond>(first, second, first_null_map, second_null_map);
    else
        return sliceHasImplAnyAll<search_type, FirstSliceType, SecondSliceType, isEqual>(first, second, first_null_map, second_null_map);
}
template <typename T, typename U>
bool sliceEqualElements(const NumericArraySlice<T> & first [[maybe_unused]],
                        const NumericArraySlice<U> & second [[maybe_unused]],
                        size_t first_ind [[maybe_unused]],
                        size_t second_ind [[maybe_unused]])
{
    
    if constexpr (is_decimal<T> && is_decimal<U>)
        return accurate::equalsOp(first.data[first_ind].value, second.data[second_ind].value);
    else if constexpr (is_decimal<T> || is_decimal<U>)
        return false;
    else
        return accurate::equalsOp(first.data[first_ind], second.data[second_ind]);
}
template <typename T>
bool sliceEqualElements(const NumericArraySlice<T> &, const GenericArraySlice &, size_t, size_t)