A minimal port of Bartosz Milewski's C++ monadic IO to typescript.
https://www.youtube.com/watch?v=vkcxgagQ4bM
Fully working in synchronous mode and asynchronous mode, using vanilla Promises.
The type system seems to work perfectly, every intermediary type can be deduced by the compiler.
The recursive monad is ready for testing. It combines IO/Promises/Maybe in the most natural way found so far. It enforces the CCC
without recursion, and requires a default value in order to run, i.e. there is essenitially a unique catch
, like clause, always right at the end. This makes the body of scripts composable using bind.
There are also various constructor/factories, to ease starting code, using the natural morphism of values and functions to the monad IO<Promise<T>>
.
Once in the monad, the algebra is generated by then/fmap
, and fbind
(functorial bind, to avoid the name clash). run
is private, because it can return bad values. Structures like this are handy for cps
, so a swap api
is provided for that (still to be tested).
The strong typing makes the system very enjoyable to use. Nothing slips past it, literally, null
is an eigenfunction till it hits the default clause, so no undefined/null values can leak out.
It all needs thorough testing, but the whole idea of the CCC
is it's just additive number theory, i.e. decidable. Every valid programme in the CCC
terminates, and does exactly what it says it will do. Each software test tried so far has worked perfectly. There's not much code, and it does what it says. Bartosz's code compiles more cleanly than with C++
, the only changes being
some extra templating to eliminate decltype/typeof,
which doesnt work as smoothly in ts
and it does in C++
. Other than this cosmetic difference, and the std::function
type erasure hack, the code is the same. ts
copes just fine without type erasure, suggesting it's inference rules are even better than C++
(last tested, the strong typed code didn't build under C++
without the hack.)
Feel free to join the chat thread in issues.
Because typescript interfaces with the outside world using non monadic apis, and all of these appear
to be a major source of bugs, often due to the defensive/obscure nature of the code involved, which is as contagious as the source of the issues: async/await/try/catch/undefined/null/?./!.
. If anyone else knows of other contagious and dangerous operations, please post them in issues.
Promises are good at doing some of what the IO monad does, but they don't compose (they only implement fmap). However an external function could implement bind, but then we gain brackets, which defeats the purpose.
Although the code is extremely succinct (thanks Bartosz!), typescript is likely to have a hard time managing the heap, due to the explicit call of new
.
Copyright (c) 2021 Fourcube Ltd. Licensed under the MIT License.