public function merge($collection)
    {
        if (!is_array($collection) && !($collection instanceof Traversable)) {
            throw new Exception\InvalidArgumentException(
                sprintf(
                    'Expected argument "array" or "Traversable"; "%s" given',
                    gettype($collection) . (is_object($collection) ? '(' . get_class($collection) . ')' : '')
                )
            );
        }

        foreach ($collection as $key => $value) {
            if ($this->has($key)) {
                if (is_int($key)) {
                    $this->append($value);
                } else {
                    if ($value instanceof CollectionInterface) {
                        $value = $value->toArray();

                        if ($this->collections[$key] instanceof CollectionInterface) {
                            $value = $this->collections[$key]->merge($value);
                        } else {
                            $value = new static($value);
                        }
                    }

                    $this->set($key, $value);
                }
            } else {
                if ($value instanceof CollectionInterface) {
                    $value = new static($value->toArray());
                }

                $this->set($key, $value);
            }
        }

        return $this;
    }