For example Null can be represented as empty string

```sql
select arrayStringConcat(['x',Null], ';');

┌─arrayStringConcat(['x', Null], ';')─┐
│ x;                                  │
└─────────────────────────────────────┘
```

But mostly it for avoiding a cast in case of Nullable Strings
```
SELECT arrayStringConcat(col0, ';')
FROM
(
    SELECT [toNullable('x')] AS col0
) AS t
```

Also I think arrayStringConcat can support any types not only Strings, it allows to avoid explicit casts.

```
SELECT arrayStringConcat(col0, ';')
FROM
(
    SELECT [1, 2, 3] AS col0
) AS t
```
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionsStringArray.h>
namespace
{
bool isNullableStringOrNullableNothing(DB::DataTypePtr type)
{
    if (type->isNullable())
    {
        const auto & nested_type = assert_cast<const DB::DataTypeNullable &>(*type).getNestedType();
        if (isString(nested_type) || isNothing(nested_type))
            return true;
    }
    return false;
}
}
namespace DB
{
namespace ErrorCodes
{
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
    extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
}
DataTypePtr FunctionArrayStringConcat::getReturnTypeImpl(const DataTypes & arguments) const