@Override
    public Type applyType(IType type) {
        if (this.specialisation != null) {
            if (this.specialisation.getArity() > 0) {
                IType applied = this.specialisation.applyType(type);
            
                String typesString;
                
                if (this.parent.typesString != null) {
                    typesString = this.parent.typesString + " " + applied.getName();
                } else {
                    typesString = applied.getName();
                }
                
                int arity = this.arity - 1 + applied.getArity();
            
                return new Type(
                    this.root, this.parent,
                    this.rootName, typesString,
                    arity, applied
                );
            } else {
                return new Type(
                    this.root, this,
                    this.rootName, (this.typesString != null ? this.typesString + " " : "") + type.getName(),
                    this.arity - 1 + type.getArity(), type
                );
            }
        } else {
            return new Type(
                this.root, this, 
                this.rootName, (this.typesString != null ? this.typesString + " " : "") + type.getName(), 
                this.arity - 1 + type.getArity(), type
            );
        }
    }