Closed rvion closed 7 years ago
here, children_
deals with (Observable (VDom e))
instead of (Observable (VDomBuilder e))
because some instance is missing. (I don't think this instance has to be complex or slightly magical, but I don't think I could have defined it outside of the library)
there is some more low hanging fruits to harvest here:
here:
type VDomBuilder e a = StateT (Array (VDom e)) (Eff (h::H|e)) a
type NodeBuilder e = VDomBuilder e Unit -> VDomBuilder e Unit
I think the NodeBuilder
type is useless complexity: to follow the initial design
(ul :: (Traversable f) => f (VDom e) -> VDom e),
ul_could be:
VDomBuilder e -> VDomBuilder e`
VDomBuilder
should have a shorter name, and probably be a newtype. this way, ide plugins for atom or vscode would display the newtype instead of the type alias.
below is a copy-paste of https://github.com/OutWatch/purescript-outwatch/issues/3#issuecomment-289284055 (I copied it here because I think it may be more relevant in this thread)
I tried various different designs: this one is best one I found so far based on all constrainsts I gave myself:
build
converts a VDomBuilder e
to a VDom e
only once at startup, and the render function is not changedI didn't test it extensively, so there might be important problems I did not see
📝 as a bonus, the monadic api could allow user to suply their own monadtransformers with some reader monad providing configuration, or globally available message bus via handlers. Halogen permit this, and this is from what I saw very usefull (I played with elm pre 0.17 and post 0.17, pux, halogen and various other UI libs, and the pure functional paradigm quickly becomes annoying without this. Here, it comes for free, at almost no cost)
Kudos to you for putting in such a large amount of effort! I really appreciate it! I'm gonna need some time to parse all of this and check the viability and weigh it against other options.
Few thoughts:
I really like the idea of having a monadic api, but also have to think about if it might be too complex for beginners or how well it translates to Scala (I'd like to have near-feature-parity)
I think that if we go through with this kind of Api VDomBuilder
should become the new VDom
as it'd be the type that gets exposed in the api, whereas the current VDom
would only be an implementation detail, so it could be renamed to something more "verbose".
Another thing I need to think about, is how we'd implement the Store
pattern, that a lot users seem to really enjoy.
That's all for now, I'm sure over the coming weeks (there's a lot of other things on the roadmap) I'll be gaining more insight and will continue to update you :)
Kudos to you for putting in such a large amount of effort! I really appreciate it!
thank you :) I also really appreciate to receive feedback too !
I really like the idea of having a monadic api, but also have to think about if it might be too complex for beginners or how well it translates to Scala (I'd like to have near-feature-parity)
I tweaked a few things trying to reduce the complexity. I think I achieved something as easy as the current version using a newtype, no other type alias, and shorter type names.
From what I saw of scala, I think scala could have the same api without much problems
I think that if we go through with this kind of Api VDomBuilder should become the new VDom as it'd be the type that gets exposed in the api, whereas the current VDom would only be an implementation detail, so it could be renamed to something more "verbose".
I completely agree.
Another thing I need to think about, is how we'd implement the Store pattern, that a lot users seem to really enjoy.
🍏 the store pattern becomes directly available with a monadic api, because the monad can provide some global stores shared amongst components
I also discovered some nice byproducts of using a monadic api (not geting in the way of beginners, but just available for more complex things): some VDomBuilder e
attribute setter could inspect the list of attributes and adapt its behaviour, etc.
2 small precisions:
1 - So far, I have found the monadic API more pleasant, correct, and powerfull, but I haven't played enough to weight the cons correctly, so don't take this arguments too seriously :)
2 - OutWatch simplicity is something I loved at first sight, and something I also really care about.
So I've bottled it down to three realistic solutions, I think:
createHandler
or an Equivalent return an Eff (rx::RX) (Observable, EventToken)
, where you'd have to map over the Eff and then let the DOM dsl work on the Eff
s instead of the actual values (There could be some Monad Transformer to help reduce BoilerPlate like ObservableT
or something like that)And of course there's 4. Don't change the current API at all and acknowledge it's impureness. Maybe change the Signature of createHandlerImpl
to return an Eff and use unsafePerformEff
in createHandler
I don't really have a huge preference right now, would probably have to build some example apps in each (which could take a while) :)
thanks for the feedback !
I've just shared what I experimented with over the last days here: https://github.com/OutWatch/purescript-outwatch/pull/9
it's not even half done, but I'm just sharing in case you have some feedback. I'll understand if you don't like the fact I did so many name change. I'll try to explain what I have in mind soon :)
@rvion If you're still interested I made #14 which I hope will be the single future of OutWatch both in Scala and PureScript :)
based on https://github.com/OutWatch/purescript-outwatch/issues/7 and https://github.com/OutWatch/purescript-outwatch/issues/3, I gave a try to some alternative monadic API
📝 operators like
==>
,<==
, and:=
are gone 📝 no more[,,,]
lists neitherit seems to works well. the only thing missing seems to be some
so components can still create dynamically subcomponents with personal handlers for inner state management.
@LukaJCB how does it look ?