vavr icon indicating copy to clipboard operation
vavr copied to clipboard

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

Open CarstenLeue opened this issue 10 months ago • 0 comments

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?

CarstenLeue avatar Feb 09 '25 11:02 CarstenLeue