Let us return to the delayed_print function from the previous section:
fun delayed_print string = fn () = printf "%s\n" string;
An alternate way to write that function and example in Mythryl is:
#!/usr/bin/mythryl fun delayed_print string () = printf "%s\n" string; fate_a = delayed_print "Just"; fate_b = delayed_print "another"; fate_c = delayed_print "Mythryl"; fate_d = delayed_print "hacker!"; fate_a (); fate_b (); fate_c (); fate_d ();
When run, this produces exactly the same result as before:
linux$ ./my-script Just another Mythryl hacker! linux$
In fact, this example may well compile into bit-for-bit the same binary code as before. The only difference is that now the fn statement constructing the fate thunk is implicit rather than explicit.
You may be tempted to think of the above delayed_print function as taking two arguments. A better way — the Mythryl way — of thinking about the matter is that the above fun delayed_print statement defines a function of one argument (a string) which then returns another function of one (void) argument: the fate thunk.
Thus, the api type declaration for such a function is
delayed_print: String -> (Void -> Void);
Which is to say, handing a string to delayed_print gives you in return a function, which when given a Void argument () returns a void value. (And in this case also prints something out, but the type system does not worry about that.)
Type arrows associate to the right, so in practice the above declaration is usually written without the parentheses:
delayed_print: String -> Void -> Void;
That looks a little confusing at first, but you quickly get used to it after seeing it a few times — and you will be seeing it a lot in Mythryl.
Such function definitions are called Curried in honor of Haskell Curry, a functional programming pioneer widely admired for having a cool name. (This kind of function definition was actually invented by Moses Ilyich Schönfinkel, but nobody wants to talk about “Schönfinkelled functions”.)
An expression like delayed_print "Just"; above is referred to as a partial application of the delayed_print function, since its final result will not be produced until the final Void argument () is supplied.
Partial application of curried functions is a concise, convenient way to produce fates. You will see this a lot in your reading of Mythryl code, and as you grow in proficiency as a Mythryl programmer you will find yourself taking advantage of this idiom steadily more frequently.