public function resolve(array $attributes)
    {
        $clone = clone $this;

        $clone->resolved = array_replace($clone->defaults, $attributes);

        foreach ($clone->types as $attribute => $type) {
            if (function_exists($isFunction = 'is_'.$type) === true) {
                if (is_null($clone->resolved[$attribute]) === false && $isFunction($clone->resolved[$attribute]) === false) {
                    throw new AttributeValueException(
                        sprintf('Invalid type of value. Expected "%s".', $type),
                        $attribute
                    );
                }
            }
        }

        foreach ($clone->notNullables as $attribute) {
            if (is_null($clone->resolved[$attribute]) === true) {
                throw new AttributeValueException('Unexpected null value.', $attribute);
            }
        }

        foreach ($clone->validators as $attribute => $validator) {
            if (is_null($clone->resolved[$attribute]) === false && $validator($clone->resolved[$attribute]) === false) {
                throw new AttributeValueException(
                        sprintf('Invalid value.', $attribute),
                        $attribute
                    );
            }
        }

        foreach ($clone->requires as $attribute) {
            if (array_key_exists($attribute, $attributes) === false) {
                throw new MissingAttributeException(sprintf('Missing attribute or option "%s".', $attribute));
            }
        }

        return $clone->resolved;
    }