model initialisation

190 views
Skip to first unread message

Alex Darlington

unread,
Aug 2, 2015, 8:53:57 AM8/2/15
to Elm Discuss
Hi,
I am struggling a little with what is probably a simple problem.

I want to store the window dimensions in my application state and it kind of works:

except I can't work out how to initialise it with the current window dimensions.
The state will have the correct dimensions as soon as the window is resized but not until then.

I know in this trivial example I can just directly display Window.dimensions but I really want to foldp on the model and have the model initialised with the right window dimensions.

Any help appreciated!

Alex.

Hassan Hayat

unread,
Aug 2, 2015, 9:08:10 AM8/2/15
to Elm Discuss
Check out this example: http://share-elm.com/sprout/55be1460e4b06aacf0e8b9a0

1) Explicitly define actions that affect your model via an update function

type Action 
  = NextFrame Time
  | Resize Vector

2) Make resize actions from Window.dimensions using Signal.map

resizes : Signal Action
resizes = 
  Signal.map (\(x,y) -> Resize { x = toFloat x, y = toFloat y }) Window.dimensions


3) Make a special mailbox to which you will send a value only when the program starts. It's a way to kick things off at the very beginning.

appStartMailbox : Mailbox ()
appStartMailbox = 
  Signal.mailbox ()

4) Send the value to the mailbox in a port

port appStart : Signal (Task error ())
port appStart = 
  Signal.constant
    (Signal.send appStartMailbox.address ())

5) Capture an initial resize by sampling on the signal associated with the mailbox

firstResize : Signal Action
firstResize = 
  Signal.sampleOn appStartMailbox.signal resizes

6) Now merge all your actions as is typical

actions : Signal Action
actions = 
  Signal.mergeMany 
    [ firstResize
    , nextframes 
    , resizes
    ]

And voila! Now you can have main just be

main = 
  Signal.map view
    (Signal.foldp update initial actions)


and it automagically works. Basically what happens is that for a very brief instant, the app will have some initial dummy window size (which could be Nothing if you prefer). Then, as soon as the program starts, it will run the task which will send a signal to the mailbox thus kicking off a new value in the signal. You can sample on that value to get an initial Resize to kick off your application or resize it before anyone notices.

Max Goldstein

unread,
Aug 2, 2015, 10:15:13 AM8/2/15
to Elm Discuss
Unexpected behavior with initial values strikes again. (Maybe we need a Signal a -> Signal a function to cause a signal to fire an event immediately with its initial value.)

Anyway, I think the more idiomatic approach* would be to not keep the window dimensions in the model. That's a concern of the view, and it's easy enough to Signal.map2 over both the model and the dimensions. Depending on what you need, you can hard-code the size of the window, padding it out in the view, or store things in the model in a relative coordinate system, 0 to 100 or something, and let the view scale it up.

* I mean, mailboxes are idiomatic, but they sure seem like overkill and incidental complexity.

Or, you might look at foldp' in the signal-extra library to see if that helps.

Alex Darlington

unread,
Aug 2, 2015, 11:33:47 AM8/2/15
to elm-d...@googlegroups.com
Thanks for the replies.

I'll go with Hassan's approach for the moment, not sure how foldp' would get me there (without some further prompting!).

It does seem messier than I had imagined though.

Anyway, here is a minimal example of Hassan's suggestion in case it helps anyone else:

Cheers!
Alex.

--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/h-WAC3kgrOU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Janis Voigtländer

unread,
Aug 2, 2015, 12:31:27 PM8/2/15
to elm-d...@googlegroups.com

For reference, here is a version of your minimal example using foldp' as suggested earlier:

import Window
import Graphics.Element as Element
import Signal
import Signal.Extra

main = Signal.map Element.show model

model = Signal.Extra.foldp' (\d s -> {s | window <- d}) (\d -> { window = d }) Window.dimensions

Don’t you agree that this is a magnitude simpler than the Task-based approach? I would also consider it more idiomatic. And no “further prompting” is necessary (if I understand correctly what you meant by that).

Note that the above will not work on share-elm, but that’s just because it relies on http://package.elm-lang.org/packages/Apanatshka/elm-signal-extra/5.3.0, which is not installed there.


--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.

Alex Darlington

unread,
Aug 2, 2015, 2:46:52 PM8/2/15
to elm-d...@googlegroups.com
Hi Janis,
Great, much simpler.

When I said 'without prompting' I simply meant I didn't understand how to use foldp'.

I needed a demonstration of how foldp' would solve the problem, as you provided.

Thanks!

Alex.

Janis Voigtländer

unread,
Aug 3, 2015, 1:30:58 AM8/3/15
to elm-d...@googlegroups.com

Ah, cool. I thought that by “prompting” you meant some signally concept, like forcing an additional event or so. :-)

@Evan, maybe an example like this (which is representative of other questions in the past), and the difference between a foldp' solution vs. the temptation to reach for Tasks in such a situation, could motivate adding foldp' to core, or at least to https://github.com/elm-lang/core/issues/322 ?

Peter Damoc

unread,
Aug 13, 2015, 11:40:53 AM8/13/15
to Elm Discuss
Hi Janis, 

Is there any way this could be adapted to the new Elm Architecture? 

I have a similar problem where I use a Signal of Action from the Window.dimensions signal

, inputs = [ Signal.map Resize Window.dimensions]

All works well except for that missing the first Resize.

Here is a minimal gist showing the issue
https://gist.github.com/pdamoc/06edd378b2af86a99f9d 


Thanks, 
Peter


--
There is NO FATE, we are the creators.
blog: http://damoc.ro/

Janis Voigtländer

unread,
Aug 13, 2015, 11:54:23 AM8/13/15
to elm-d...@googlegroups.com

I guess this would require StartApp using foldp' instead of foldp. So, a feature request there?

Peter Damoc

unread,
Aug 14, 2015, 1:05:10 AM8/14/15
to Elm Discuss
Hi Janis,

I tried o naively replace the fold in StartApp:

            Signal.foldp update config.init inputs

 with 

            Signal.Extra.foldp' update (\a -> update a config.init) inputs

but I get a strange 

Non-exhaustive pattern match in case-expression.
Make sure your patterns cover every case!

What am I missing here? 

Thanks,
Peter

Janis Voigtländer

unread,
Aug 14, 2015, 1:25:52 AM8/14/15
to elm-d...@googlegroups.com

Due to this line and this line, your update a config.init tries to pattern-match a Nothing (coming from messages.signal) against a Just action (in the first argument position of update). An immediate solution would be to replace messages.signal :: List.map (Signal.map Just) config.inputs by List.map (Signal.map Just) config.inputs ++ [messages.signal] in the first of those places mentioned above.

However, that’s not to say that should necessarily be how StartApp works in general. For example, if config.inputs has several signals, you will only take the initial value of the first of them into account (which in your case is okay, since there is only one signal in inputs).

So, there are design considerations here that should be made for StartApp: Should the package support model initialisation based on the initial value(s) of input signals? If so, how exactly? Maybe bring those up as issues in the StartApp repository.

Peter Damoc

unread,
Aug 14, 2015, 2:35:48 AM8/14/15
to Elm Discuss
I've opened an issue on the StartApp repository. 

Thanks for all your help! 

Peter Damoc

unread,
Aug 14, 2015, 2:42:08 AM8/14/15
to Elm Discuss
I've opened an issue on the StartApp repository. 

Thanks for all your help! 
On Fri, Aug 14, 2015 at 8:25 AM, Janis Voigtländer <janis.voi...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages