I want to talk about effective handlers in particular in the fusion language and how they
are used in there for error handling and how designed by contract is done in the fusion
language. A bit background to myself and how you can reach me. Putting in short, I worked
on computers all of my life with a long-term working on Java implementations for safety
critical applications and now since five years I'm working on the fusion language and now
within Tokyo Software Small Company where I lead a small team of four developers working
on fusion. The overall view of my talk is I will start with a very quick overview of the
fusion language, then give you an example of error handling that will then lead me to
explaining what design by contract is, then I will explain what effect handlers are and how
they can be used to implement design by contract and then how a hierarchy of errors,
foldable, could be made and if there's time I'll talk a bit about a cool feature in that context
which is type constraints. So the quick entry to fusion, I wrote some stickers maybe if somebody
is interested in us, then I'll take as many as you like. The idea behind fusion is to have
a simple language to basically base everything on one concept, the concept of a fusion
feature and the idea behind that is that our systems are becoming more and more safety critical
and we want to make it easy to develop correct code for those systems and making it easy by
having tools that help the developers life to correct to analyze the correctness of the application.
So fusion language is statically typed, it is polymorphic in several ways, it has union types,
it has parametric types, generics and it has object oriented style inheritance and it's a pure
functional language where everything that is non-functional, non-pure is wrapped into effects.
A start of with an example, my very small example here is a function that takes an x and returns
to string that shows x and the square of x and the x is any numeric parameter. Fusion uses a
syntax sugar so actually this is a short form for a function that actually has two arguments.
There is a type parameter n that is numeric and a value argument x that is a value of that type.
So basically this is a generic function here but I stick with the short version.
And I can now run this giving different arguments of different types, here's an integer
fraction or complex and I will go to the fusion website where I have this talk and where you see
the examples so I can run this example now and it will then calculate the squares and print those
free strings. If I extend the example and call the square function with a byte, an 8-bit integer
and provide the value of 30 that will not so the result will not fit into the byte.
What will happen is I will get an awful error in the middle of the code. So
the question is now how can we do this error handling better. One approach is we could just add a test
in our square implementation if the multiplication would overflow and perform the calculation only
if it doesn't and otherwise we panic and if we run this so we check this and we panic.
Panic is an effect so we have to mark this in the signature of the function that this function requires
the panic effect to be executed. And when we run this we get the default implementation of the
panic effect which then produces this overflow for 30 output. The problem is it fails here the problem
is who is actually to blame for that? Where is the bug? Is it in the square function? That panic
or is it the caller who just provides arguments that cannot work with that function?
This is where designed by contract comes into play. Design by quantity of the
ideas that we formally specify for every function. What preconditions has to hold has to be
satisfied by the caller to call that function and specify then what guarantees that function can
give after it has executed the post conditions. So the function provides a formal contract for
via the pre-inpost conditions and this is used for several things. It can be used for runtime
checks like the panic we had right now but it can also be the basis of static analysis tools to
verify correctness or to generate tests and lots of other nice things. So doing the same function
with pre-inpost conditions we can now put the at the pre-condition that there must not be an overflow
when multiplying expire itself and we could add post conditions like the result is never the empty string
and the implementation of the function becomes very simple now and when we run this
we get a pre-condition for which clearly indicates that the caller here then provides a type
that doesn't fit with the desired calculation. Now fusion uses effect purpose you've seen that
in the panic example where panic effect was used so let me quickly introduce to you what effect
are. An effect handler is a set of operations and these operations may have
side effects like reading or writing data to a file. These operations may produce a result
like when you read from a file you might want to get the data that was read or an operation
might also abort which is what typically a call to panic would do and to use the operations
of an effect handler the effect must first be instated for the context where these operations are
supposed to be used. And effect handler for error handling this is now a part of the standard
library of fusion where a handler forable is defined which inherits from effect so it's an effect
handler and this is the template for errors to be defined in the fusion language and this has
a feature try that would instate an instance of that effect and run some code and
within that code that effect or that code can cause this error. Here's an example this can be used
to create your own error, my fault within this case and we can use this we can call try and
in within the code that is executed here we can then cause that error and we have a way to catch
this error looks very similar like exception handling in other languages so yeah I've explained that
now using going back to the the panic version of the spare example using these
effect handlers we can now instate our own instance of a panic handler and run the code from
the spare and in case that panic can catch that error print a message and we call square again
with a larger the actually unlimited integer type to run it again. If you run this we see
that we got that error and we're trying again and then we got it get a proper result.
Now, question is what happens for pre and post conditions only have the pre condition here to
make the example a bit simpler and fusion as I said uses a lot of syntax sugar actually pre conditions
are just syntax sugar for a pre condition fault error very similar to the panic example and
that means that we can also instate our own version of the pre fault and run code with that
and catch this so basically this condition if that fails would cause then the same behavior as
the previous example so this causes a pre condition fault which then ends up here and we can run this
again and it runs successfully. Now, we have a number of fallables in our basic library and
showed you panic pre fault at this fault fault is checks and there could be user defined and
many more. For proper error handling what we would like to have is some kind of hierarchy if you
use to Java you have this throwable hierarchy where you can catch throwable or arrow at the different
areas so the question is how do we do that in fusion and the solution is we have a cascade of
fallables so we have a most general fault which is the most basic error and then panic the default
implementation of the panic fallable actually is implemented using the fault so it doesn't inherit
from that but the implementation that propagates the error further to a fault and the pre condition
and post condition faults you have seen they don't directly propagate to fault but they
propagate to some intermediate a foldable which is a contract fault and that then propagates to that
fault so the user can now decide what level of falls it would like to handle when it wants to
catch those. There's also check falls that could be IO falls or network defaults in all
points so on. Do we have two minutes? I have four minutes okay and I'll quickly talk about
type constraints because they are cool feature in this context if I go back to the square function
and I call it now where a huge floating point argument and I expect this to fail because this
overflow but it doesn't fail I still get the infinity and the reason is because floating points
is just that this doesn't overflow on multiplication just perfectly produce the infinity.
If I want to catch this error what I can do is I can actually put a constraint on the type
parameter I can say if my type parameter is a float I want to have a stricter precondition here and
if I do this now I can also in this specific case get an error for that so we can really
work with these type parameters pretty much like compile time values doing all sorts of special
things there. So that's it I come to you to the end. The status of fusion it's still
underdeveloped into the whole project. The language definition is getting more and more stable.
We have back ends for Java VM Java by code and C code and we have foreign function interfaces
more or less working for Java and for C we're working a lot on the basic libraries and static
analysis tools and we have first applications that are being developed and since last month we
are part of European project in the idea framework called green code with lots of partners all
of course rule Europe we're trying to improve that language. That's it you can find more information
at the sandals please follow us give us stars.
Questions?
Can you repeat?
Let's say that you have a function that can produce multiple type of effects like I've
followed some of those you show how you do with those cases. That would mean that the function
in that signature would have to list all of those effects as effects that are required by this function
and now when this function is used the call can then be side what it wants to do it can
run this code with specific handlers for part of the effects that it wants to to handle and leave
the rest to the default handler which is a fault or it could just be more general and
handle the more generic fault in any cases and catch all the errors that could happen in
there. You can have multiple touches. They can be nested so whatever matches would then be used.
You don't need to cover all of them you can have so you just use the default for whatever you don't
handle. But if you use the default that means that your code yourself actually causes that effect
it propagates and the call of that has to handle that.
If you so you should some examples with three conditions assuming you have
enough information at compile time with precise types like single type sorry
payment types can you avoid having to install handler like can you statically check the things.
What kind of things do you want to have checked statically?
So if you know statically but the input of square is like 10 you know it's never going to overflow.
So in that case do you still need to install handler or can you statically know that you don't need it
and then optimize it away? What we do right now already is we specialize the code for
these specific types like for the for the float there's only the specific version for float that
is put in and if it's called with an integer the specific handling for float is completely optimized
out. What we don't do yet is propagating constant values that are passed in there but it is a
pretty straightforward compiler optimizations of specializing a call for a constant argument at this
pass so we don't do it yet at the moment but that eventually we'll have to have to be done and
it's not very difficult. Time for one more question or if you use this one.
Ah, this one. Ah, okay, this one to Andy.
The tri function is is a function in our standard library for the fallable effect and it does quite
a bit of thing it actually creates an instant instance of that effect in states it and then calls
the code that is passed to that function. Yeah. Okay, I think I'll have to leave. Thank you.