How can I package/abstract code that uses ports?

126 views
Skip to the first unread message

Peter Damoc

unread,
29 July 2015, 4:12:17 am29/7/15
to elm-d...@googlegroups.com
Hello kind people, 

I have a piece of code that I need to abstract away in a module. 

The code uses ports to save to local storage like TodoMVC example. 

How can I abstract the ports code in a module? 

I've searched a little bit and I've found some github repositories that have a Native folder. 
Is there any documentation on this? 

For people who want more concrete information, I've implemented a small snake clone part of my learning Elm project (challenge 5) and now I have to abstract the High Score functionality so that it can be used by other games. 
https://github.com/pdamoc/elmChallenges

Thank you in advance,
Peter

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

Jeff Smits

unread,
29 July 2015, 12:01:20 pm29/7/15
to elm-discuss
Ports are an escape mechanism for an app. If you feel the need to abstract stuff away, then Native is an unchecked way to call JavaScript. Because you can abuse it very easily, it's not documented (to discourage people from reaching for it too soon as an escape mechanism to do side-effects). The "correct" way to use it with local storage would be to implement JavaScript to handle new Tasks that are specific to local storage.
I'm not an expert on the details of this, so this is all the info I can provide you with. Good luck with your elm challenges :)

--
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.
For more options, visit https://groups.google.com/d/optout.

Evan Czaplicki

unread,
29 July 2015, 12:39:27 pm29/7/15
to elm-d...@googlegroups.com
Joey is currently working on dead code elimination, and after that's done, I expect to be making a real API for these native bindings. Right now, there is just a hack that certain folks have used. So I'd think of this as "this feature is in the pipeline" not as "how do I do that weird native hs thing some packages do?"

For other folks on the list, please talk about it this way. There is no real public API for this, but it's coming.


--
Sent from Gmail Mobile

Jeff Smits

unread,
29 July 2015, 12:46:48 pm29/7/15
to elm-discuss
Sorry, I didn't know the status on this had changed. @Evan, can you do another announcement of your current planning? Just knowing roughly what's in the pipeline in what order would be nice, to avoid misconceptions like these for example.

Max Goldstein

unread,
29 July 2015, 1:01:08 pm29/7/15
to Elm Discuss, eva...@gmail.com
One trick I've had some success with in a single app with many modules is to define a (signal of) Task(s) that, when run, does all of the effectful work the module needs. You can use a standard name across all your packages, and then run them all in the main module. This makes for a certain amount of boilerplate, but it avoid native modules.

Peter Damoc

unread,
30 July 2015, 3:49:25 am30/7/15
to elm-d...@googlegroups.com
On Wed, Jul 29, 2015 at 7:39 PM, Evan Czaplicki <eva...@gmail.com> wrote:
So I'd think of this as "this feature is in the pipeline" not as "how do I do that weird native hs thing some packages do?"


So, just for my own clarity, is it possible to solve the challenged I received (abstraction of the High Score module that uses localstorage) with current Elm without resorting to hacks/undocumented features like Native? 

If this is not yet possible, I can stop for a moment and focus on something else. 

Dénes Harmath

unread,
30 July 2015, 5:37:11 am30/7/15
to Elm Discuss, pda...@gmail.com
Based on Jeff's and Max's answer, let me summarize the options you have:
  • The "unsafe" option: You use the yet undocumented and subject-to-change Native API.
  • The "safe" but "boilerplate" option: You just declare the signals (without ports) in the used modules and make sure the main module declares ports which perform these signals.

Peter Damoc

unread,
30 July 2015, 6:18:03 am30/7/15
to Elm Discuss
Hi Denes,

I don't see how the "safe" version might work without forcing on the final user a big chunk of the functionality. 
The way I understand it, it would be the equivalent of saying "Here is this 'High Score that saves to local storage' module but you have to implement the 'saves to local storage' yourself."

I'm perfectly fine with "this feature is in the pipeline", I just wanted to make sure that I wasn't giving up on the challenge too soon. ;) 

Thank you for your answer
Peter

Maxwell Gurewitz

unread,
30 July 2015, 11:40:51 am30/7/15
to Elm Discuss, pda...@gmail.com
Hi Peter,

I'm new to this discussion board.  I have now idea if this is ideomatic, but this is what I do,

main : Signal Html
main =  
  Signal.map view model

model : Signal Model
model =
  Signal.foldp update initialModel actions.signal

port asyncPort : Signal (Task x ())
port asyncPort = asyncActions.signal

view : Model -> Html
view model = baseLayout [ ((router model.path) model) ]

Then I can push tasks to the asyncPort e.g. here's a link which sets the page's path (without reloading the page)

a [ onClick asyncActions.address (Tasks.setPath path) ] [ text name ]

Hope that helps!

Max

Max Goldstein

unread,
30 July 2015, 12:43:36 pm30/7/15
to Elm Discuss, pda...@gmail.com, maxth...@gmail.com
Maxwell, that's pretty much what I was trying to get at with the "safe" route. You package up as much as you can into one exported signal of tasks, and then run that in main.

Peter Damoc

unread,
31 July 2015, 3:03:43 am31/7/15
to Maxwell Gurewitz, Elm Discuss
Hi Max,

Thank you for your answer. It made me realize that I was not clear. 
My problem relates to the fact that in order for my code to work, I have to write JS in a .html file. 
It is very little JS but still I have to write it or the app doesn't work. 
This is what I do not know how to do. 

Ports that are used without corresponding JS code in HTML, I imagine that pose no problem. 
i.e. in my challenges, Challenge No. 4 uses `ports` to get the information from github. I have not tried to package it in a module but I do not expect to encounter any trouble. The troubles are uses of ports like the one in Challenge No. 5. That is what I do not understand how to approach. 
https://github.com/pdamoc/elmChallenges

Thanks again,
Peter
Reply all
Reply to author
Forward
0 new messages