Skip to content
This repository has been archived by the owner on Apr 23, 2022. It is now read-only.

Installation breaks Debugger's history export #5

Open
armatures opened this issue Jan 24, 2018 · 3 comments
Open

Installation breaks Debugger's history export #5

armatures opened this issue Jan 24, 2018 · 3 comments

Comments

@armatures
Copy link

armatures commented Jan 24, 2018

Hello!
Thanks for building this cool and useful thing! I've been very happy with it since installing, but encountered some trouble today while debugging. I built my app with the debug flag and clicked in the history pane, then tried to export it. I got the following message:

Cannot use Import or Export
The Msgs.Msg type of your program cannot be reliably serialized for history files.
Functions cannot be serialized, nor can values that contain functions. This is a problem in these places:
Control.Control can contain functions.
The good news is that having values like this in your message type is not
so great in the long run. You are better off using simpler data, like
union types, in your messages. From there, your update
function can pattern match on that data and call whatever functions, JSON
decoders, etc. you need. This makes the code much more explicit and easy to
follow for other readers (or you in a few months!)

So that's a bummer! Do you have any idea for workarounds?
Thanks!

@armatures
Copy link
Author

In exploring this issue, I've found an additional unfortunate constraint: if the main Model type for your application needs to reference your main Msg type, your Msg type can't contain anything defined in your Model file or you'll get a circular dependency. If there was a way to access the message contents of the Control.Wrapper in Control.Debounce.trailing, I imagine I'd be able to hold something other than a top-level Msg in the Control.State. Then the update function ends up as a case statement on the type populating the Control.State field.

        Debounce ubikMsg ->
            let
                ( newModel, cmdDebMsg ) =
                    Control.update (\s -> { model | pendingSave = s }) model.pendingSave ubikMsg

                ubikToMsg debounce =
                    case debounce of
                        Save ->
                            PersistEmail model.email

                        Cancel ->
                            NoOp
            in
                ( newModel, Cmd.map ubikToMsg cmdDebMsg )

Any ideas on how to keep from rolling my Msg and Model types in the same file?
Thanks!

@mpizenberg
Copy link
Owner

Thanks for the feedback! That's indeed quite unconvenient! For the context, I built this thing at the time of elm 0.17 and there wasn't the debugger. The tips given in the error message are also very right.

Since 0.19 is approching, it might be a good thing to rethink a bit the way this package work. Last month I wrote down few ideas in issues #1 #2 #3 and #4 . This is definitely a good issue for rewrite!

The whole reason for the existence of the wrapper was to be able to emit controlled (debounced or throttled) messages hidden as normal user messages. Like so, all messages are emit as the same user Msg type. And I could choose to just generate a Cmd containing the original msg, or wrap an internal Control msg inside a Cmd that would trigger at a later time. I think I wanted to do so to avoid a little bit of boilerplate on the user side but now I think it's probably not a good idea.

This whole design is like this because at the time, I wanted to explore and try to understand state monads. As a consequence, all the logic (functions) is wrapped inside the messages emitted instead of inside an update function. This pattern is warned in a lot of elm places as very dangerous (that I didn't know at the time ^^).

To summup, I think your issue is very relevant. However, it would imply a complete rethink of the package architecture. So it should drive a "practical" rewrite of this package for 0.19 instead of my personal "state monad" exploration. I've learned a lot of how to better structure elm code now, but the bad news is that I was doing this alone and don't have time now to work on it ...

If you think you can do it without a complete rewrite, don't hesitate to try. Otherwise, for the time being, it would probably be better to try another package.

@armatures
Copy link
Author

Thank you for such a prompt and thoughtful response! I must admit that the monadic parts of this library are over my head, but that shouldn't stop me from trying to work with them! I'll see if there are any alternatives that have already built something like what I'm looking for, and maybe come back to spike on this one if my schedule accommodates. Thanks again!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants