Sintrastes/hafly

Implement reactive polymorphism.

Opened this issue · 5 comments

Implement reactive polymorphism.

Really this could be more generally any kind of "functorial" polymorphism.

One question I have about this is: When would this be applicable?

Does this also apply to IO (and any other monad/functor), or would it only be for specified cases?

It might make sense to use a special syntax for this. e.x. printLn !readLn makes it clear that we're saying "Print the result of readLn, rather than printLn readLn` ("Print the readLn function itself"), which doesn't make a whole lot of sense and should probably crash.

Thus, this might be a slightly different syntax, but essentially the same idea as idiom brackets from Idris.

It would also work pretty similarly to how .bind() works in arrow-kt.

We may be able to make the $ sigil for string templates do the double-duty of also !-binding any monadic results, but that may be problematic, as there are examples such as the list monad where we may want to actually display the list (rather than binding the list).

So we may require something like "The count is $!count" for binding reactive state.

Maybe to deal with ambiguities, we could also borrow a page from arrow-kt, and introduce a context with something like:

[monad-name] { block where ! can be used to bind }

So in the reactive UI example, this might look something like:

UI = Column {
    count <- state 0
    
    btn <- Button "Click me!"
    
    when btn.clicked {
        count := count + 1
    }
    
    Text $ State { "You clicked me $count times!" }
}

So maybe not as nice as I originally imagined for this, but I think this is less ambigious, and still less clunky than explicit binds/maps. This would also be more similar to idiom notation, as we have explicit blocks.