Combine two functions to create a function with a union type input

38 views
Skip to first unread message

manuel rascioni

unread,
Nov 20, 2016, 4:21:29 PM11/20/16
to ceylon-users
Hi,

I've wrote this code, in which I combine a function from String to String and another one from Integer to String to create a new function that has input String|Integer and returns a String:


String(Integer|String) mix(String(Integer) f, String(String) s) {
    return ((Integer|String arg) => 
        switch(arg)
        case (is Integer)
            f(arg)
        case (is String)
            s(arg)
    );
}

value fn4 = mix(Integer.string, String.uppercased);
print(fn4("ciao"));
print(fn4(160));

Then I tried to generalize it to have generics inputs of the functions:

String(F|S) mix<F, S>(String(F) f, String(S) s) {
    return ((F|S arg)
        => switch (arg)
        case (is F)
            f(arg)
        case (is S)
            s(arg)
    );
}

But (sadly) this piece of code doesn't compiles, saying that cases are not disjoint.

I was wondering why?

Is it because I can't guarantee that F doesn't extends S?

Is there a way to do it?

Gavin King

unread,
Nov 20, 2016, 4:23:19 PM11/20/16
to ceylon...@googlegroups.com
Right, the issue is that if we have two type parameters, we just can't
be sure that they don't refer to overlapping types. The branches of a
switch are required to be disjoint.

OTOH, the branches of an if statement are *not* required to be
disjoint, so you can use "if (is)" instead of switch.
> --
> You received this message because you are subscribed to the Google Groups
> "ceylon-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to ceylon-users...@googlegroups.com.
> To post to this group, send email to ceylon...@googlegroups.com.
> Visit this group at https://groups.google.com/group/ceylon-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/ceylon-users/b471d7fa-550a-45aa-97b4-12b2b0991d24%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Gavin King
ga...@ceylon-lang.org
http://profiles.google.com/gavin.king
http://ceylon-lang.org
http://hibernate.org
http://seamframework.org

manuel rascioni

unread,
Nov 20, 2016, 5:29:15 PM11/20/16
to ceylon-users
I've tried, but with the if statement it seems that the union type can't be "cast" (don't know if is the right term) to F.

<String|Exception>(F|S) mix<F, S>(String(F) f, String(S) s) {
    return ((F|S arg) {
        if (arg is F) {
            return f(arg);
        }
        else if (arg is S) {
            return s(arg);
        }
        else {
            return Exception("");
        }
    });
}

Saying:
argument must be assignable to parameter type: 'F|S' is not assignable to 'F'

I'm pretty new to Ceylon, the type system seems very interesting, I'm exploring it :)

John Vasileff

unread,
Nov 20, 2016, 5:45:02 PM11/20/16
to ceylon...@googlegroups.com
There are actually two ways `is` can be used. The `arg is F` form is just a Boolean expression. The other, `is F arg`, is a condition that will narrow `arg` to the type `F`.


HTH,
John

manuel rascioni

unread,
Nov 21, 2016, 4:00:33 AM11/21/16
to ceylon-users
Thank you!

Now I made it works!
Reply all
Reply to author
Forward
0 new messages