Skip to content

Should Function1.curried() be covariant in its return type? #2989

@CarstenLeue

Description

@CarstenLeue

I wonder if

    /**
     * Returns a curried version of this function.
     *
     * @return a curried function equivalent to this.
     */
    default Function1<T1, R> curried() {
        return this;
    }

should probably rather be

    /**
     * Returns a curried version of this function.
     *
     * @return a curried function equivalent to this.
     */
    default Function1<T1, ? extends R> curried() {
        return this;
    }

because

    /**
     * Applies this function to one argument and returns the result.
     *
     * @param t1 argument 1
     * @return the result of function application
     * 
     */
    R apply(T1 t1);

is covariant in R by default. Consider the following example:

import io.vavr.Function1;

public class Function1Test {

    public static class A {
    }

    public static class ASub extends A {
    }

    public interface MyFunctionA<T1> extends Function1<T1, A> {

        @Override
        default Function1<T1, A> curried() {
            return this;
        }
    }

    public interface MyFunctionASub<T1> extends MyFunctionA<T1> {

        @Override
        ASub apply(T1 t1);

        @Override
        default Function1<T1, ASub> curried() {
            return this::apply;
        }
    }

    @Test
    public void testHierarchy() {

        final MyFunctionASub<String> f = s -> new ASub();

        final ASub as =f.apply("");
    }

}

The override of curried in MyFunctionASub should reflect that its apply method returns ASub but this would require the ? extends R signature in Function1.

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions