[elm-discuss] Re: Function equality again

2016-10-12 Thread James Wilson
I basically agree - something as basic as using an equality test should not 
have any chance to cause a runtime error in any case; in the case of 
functions it should be based on referential equality, which I think does 
the right thing in any sane case.

On Wednesday, 12 October 2016 17:48:12 UTC+1, Mark Hamburg wrote:
>
> As discussed elsewhere, the runtime exception related to function equality 
> comparisons is a lurking time bomb for code that is really only addressed 
> on a multi-developer project by being paranoid both about functions in data 
> structures and use of the equality operator. Both points of paranoia get in 
> the way of writing "good" code. There are other arguments around things 
> like serialization for avoiding using functions in some places, but there 
> are lots of other places where it is extremely useful to put functions in 
> data structures. (Imagine writing an effects manager if it couldn't store 
> functions in its data structures.) 
>
> Full equality tests are, as I understand it, undecidable. That doesn't 
> mean, however, that some limited analysis can't prove equality in most of 
> the conditions that matter. In fact, the existing code doesn't always throw 
> an exception. It only throws an exception if an "allocation identity" test 
> fails. One could extend this to looking at the "code pointer" and 
> allocation identity for the closure values and probably get many of the 
> remaining cases that mattered. It's just a matter of how far one wants to 
> push when trying to prove or disprove equality and I'm not arguing for a 
> particular limit here. 
>
> Rather, I think the central issue is around what happens when we give up. 
> At that point, there are two choices: throw a runtime exception as happens 
> now or return false. As mentioned above and discussed at further length 
> elsewhere, the runtime exception leads to paranoid coding. What are the 
> issues with returning false? The big problem with returning false is that 
> this means that some compiler optimizations might then change cases that 
> returned false without the optimizations into cases that returned true and 
> people become understandably uncomfortable with the possibility that 
> compiler optimizations could change the meaning of programs. And with that, 
> I've more or less wanted a "return false" answer but convinced myself that 
> throwing an exception wasn't unjustified and that maybe what we needed 
> instead was type system support to avoid the issue. 
>
> But then this morning's discussion of the virtual DOM had me realizing 
> that runtime optimizations around when the render-diff-patch algorithm gets 
> run create significant potential for variable program behavior. We embrace 
> these optimizations even though they introduce non-determinism. Now, its 
> non-determinism at the level of the physical DOM rather than the values 
> produced in Elm itself — i.e., runtime v linguistic non-determinism — but 
> its non-determinism in one of the most fundamental parts about how Elm is 
> generally used so that distinction seems somewhat arbitrary. 
>
> I think Elm makes the right call on the DOM. Maybe it should log cases 
> where the DOM logic can recognize that there might be a problem, but I 
> think this is overall a tradeoff worth making. 
>
> But by the same argument, I think Elm programs would be better if the 
> runtime exception for function equality comparisons was replaced with a 
> false result even though it might actually be true. And if it's really 
> irksome, then it could generate a log statement as well. 
>
> Mark 
>
>
>
>

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


Re: [elm-discuss] Elm, Objects and Components

2016-09-20 Thread James Wilson
I haze thought about using web components like this too. You could even go a 
step further and have web components that embed Elm inside themselves the same 
way you can whack Elm into any other element. So perhaps a collection of Elmish 
web components points one path forward! 

The other nice thing about embedding web components into Elm as easily as we 
can is that they can be used to wrap native JS things into El as well. For 
example one might make a web component to render a google map based on ita 
attributes, and in Elm we just Html.node "google-map" [] []. Definitely 
something I need to play with more!

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


[elm-discuss] Re: Problem with Html.Lazy

2016-09-13 Thread James Wilson
I had similar feelings; lazy uses a magical referential equality between 
things that afaik isn't exposed elsewhere; to me it would be more 
obvious/clear if it used the same sort of equality as everything else (==), 
which I'd hope would be able to short circuit the meat of the checking if 
referentially equal anyway.

Basically, I'd be interested to hear more about the decision to use 
referential equality with lazy too :)

On Tuesday, 13 September 2016 12:09:05 UTC+1, Yosuke Torii wrote:
>
> Hi,
>
> I have a question about Html.Lazy.
>
> Now I'm optimizing rendering using Html.Lazy but I feel it is difficult to 
> use. I found the arguments are not often *referentially* equal and the 
> view functions are unfortunately called. There are some problems around 
> this.
>
>
> 1. Sometimes new values are created every time.
>
> view model = lazy someView { data = model.data }
>
> 2. Views do not know how arguments are passed.
>
> view model = lazy grandchildView model
>
> 3. It is not easy to know if optimization succeeds or not.
>
> view model = Debug.log "Unfortunately called!" <| text (toString model)
>
>
> I made a demo to describe this problem.
>
> Source: https://github.com/jinjor/elm-issues/blob/master/src/HtmlLazy.elm
> Demo: https://jinjor.github.io/elm-issues/html-lazy.html
> (9 example views, but 4 ~ 9 are not optimized unfortunately)
>
> So my question is:
>
>- Is it a bad idea to compare by *normal *equal? 
>- Have anyone already solved this problem?
>
>
> Thanks.
>

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


Re: [elm-discuss] Unrelated modules having ports with the same name

2016-08-31 Thread James Wilson
There is as I understand it nothing wrong with compiling multiple modules with 
a main function using one command. It's very useful if you want many separate 
Elm widgtts that share the same runtime and library code. As I understand you 
can do:


Foo.hs:

module Foo
main = HTML.App.Program...

Bar.hs:

module Bar
main = HTML.App.Program...

elm-make Foo.elm Bar.elm --output combined.JS

And combined.JS will expose Elm.Foo and Elm.Bar, which can separately be 
instantiated but share the same runtime and things.

All of this to say, I would assume that ports should be scoped by the main 
module that imports them and that this is a bug.

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


[elm-discuss] Re: Task ports: A proposal to make it easier to integrate JS with Elm.

2016-08-24 Thread James Wilson
It wouldn't be hard to provide a promise shim, although I'm not sure how I 
feel about that. 

Callbacks would be the well supported option, although the interface to 
promises maps better. Promises can only resolve/reject once, always return 
something, and the function attached to the task port could just return a 
plain old value too, which would be equivalent to resolving a promise 
immediately with that value. This means that for synchronous calls the user 
can just provide a regular function to the JS side of the task port and not 
do anything Promisy at all. If we want to provide callbacks instead I would 
be tempted to provide 2 - one for resolve and 1 for rejection, and then add 
the promise logic (first one to be called wins) behind the scenes.

In the promise scenario, these are all valid:

App.ports.myTaskFunc = function(val){
return (val + 2) //equivalent to returning a Promise that is resolved 
to (val+2) immediately
}

App.ports.myTaskFunc = function(val){
return new Promise(function(resolve){
resolve(val+2)
reject("err") // this is ignored since we've already resolved.
});
}

App.ports.myTaskFunc = function(val){
return Promise.resolve(val + 2)
}


And the equivalent callback style might look like:

App.ports.myTaskFunc = function(val,resolve,reject){
resolve(val+2);
reject("err") // this is ignored since we've already resolved.
}





On Wednesday, 24 August 2016 18:42:16 UTC+1, Maxwell Gurewitz wrote:
>
> My only comment would be that the interface should not rely on promises, 
> which are not supported by IE.  Instead it should use node style callbacks.
>
> On Saturday, August 13, 2016 at 8:31:07 AM UTC-7, James Wilson wrote:
>>
>> The problem
>>
>> ports as they stand are fundamentally incompatible with Tasks. Being 
>> backed by Cmd's, they are harder to compose. A frustration of mine is that 
>> often we are directed to "just use ports" when a proper interface to some 
>> native API is not yet available, but this leads to our Msg types growing 
>> and more significant changes being required when eventually the proper 
>> interface is made available.
>>
>> Also, many JS interop things I find myself wanting to do are 
>> fundamentally one-shot functions which I expect a result back into Elm from 
>> immediately, or otherwise just want to compose with other Task based 
>> things. Some examples that come to mind of one-shot tasks you may want to 
>> compose rather than use the streaming interface that ports provide:
>>
>>- Getting items from local/sessionStorage
>>- .. really, most things involving working with the Web API that 
>>arent yet implemented in Elm.
>>- Embedding JS widgets into Elm elements
>>- Using a JS library for doing things like hashing passwords or 
>>obtaining some data back from some custom service
>>- Interacting with things like Electron for creating apps that can 
>>run in the desktop and interact with the filesystem etc.
>>
>>
>> The solution
>>
>> Task ports. The idea is that these are defined the same way that Ports in 
>> elm currently are, but they return a Task type rather than a Cmd or Sub 
>> type. On the JS Side, we attach a function to the Elm app that returns a 
>> Promise, and on the Elm side we wait for the Promise returned to reject or 
>> resolve, and marhsall the error or result from the promise into the error 
>> or result type required by the Task type of the port.
>>
>> Let's see how this might work:
>>
>>
>> *Ports.elm:*
>>
>> port apiSession: Task String SessionId
>>
>>
>>
>> *Main.elm:*
>>
>> import Ports
>> import Json.Decode as Decode
>> import Task exposing (andThen)
>>
>>
>> -- get an API session from JS land and make an http request using it
>> -- given some path and a decoder to decipher the result:
>> apiRequest : String -> Decoder a -> Task ApiError a
>> apiRequest path decoder =
>>   let
>> headers sessId =
>> [ ("Content-Type", "application/json")
>> , ("MyApp-SessionId", sessId)
>> ]
>>
>>
>> req sessId = Http.send Http.defaultSettings
>> { verb = "POST"
>> , headers = headers sessId
>> , url = path
>> }
>>
>>
>> decodeResponse res = Decode.decodeString decoder -- ...handle error 
>> etc
>>   in
>> Ports.apiSession `andThen` req `andThen` decodeResponse
>>
>>
>> *App.js:*
>>
>> Elm.Main.ports.apiSession = function(){
>> return 

Re: [elm-discuss] Record update compiler bug? (Elm 0.17.1)

2016-08-14 Thread James Wilson
ah sorry, I should have perused that first :)

On Sunday, 14 August 2016 08:37:56 UTC+1, Janis Voigtländer wrote:
>
> Check the compiler repository. This issue is already reported/covered. 
>
> Am 14.08.2016 um 10:11 schrieb James Wilson <jam...@gmail.com 
> >:
>
> In my update function I have something like:
>
> LoginPassword str ->
>   let login = { model.login | pass = str }
>   in ({ model | login = login }, Cmd.none)
>
> Which I was hoping would correspond to updating the "pass" field of the 
> record at model.login. Instead I get a compiler error:
>
> -- SYNTAX PROBLEM - 
> Main.elm
>
> I ran into something unexpected when parsing your code! 
>
> 94|   let login = { model.login | name = str } 
>  ^
>
> I am looking for one of the following things: 
>
> "|" 
> an equals sign '=' 
> more letters in this name 
> whitespace 
>
> Detected errors in 1 module.
>
> Breaking it down a bit more to:
>
> LoginPassword str ->
>   let
> lm = model.login
> login = { lm | pass = str }
>   in ({ model | login = login }, Cmd.none)
>
> Seems to be fine.
>
> I feel like this is a compiler bug; is there any good reason why it 
> shouldn't work as expected?
>
> -- 
> 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.
>
>

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


[elm-discuss] Record update compiler bug? (Elm 0.17.1)

2016-08-14 Thread James Wilson
In my update function I have something like:

LoginPassword str ->
  let login = { model.login | pass = str }
  in ({ model | login = login }, Cmd.none)

Which I was hoping would correspond to updating the "pass" field of the 
record at model.login. Instead I get a compiler error:

-- SYNTAX PROBLEM - Main
.elm

I ran into something unexpected when parsing your code! 

94|   let login = { model.login | name = str } 
 ^

I am looking for one of the following things: 

"|" 
an equals sign '=' 
more letters in this name 
whitespace 

Detected errors in 1 module.

Breaking it down a bit more to:

LoginPassword str ->
  let
lm = model.login
login = { lm | pass = str }
  in ({ model | login = login }, Cmd.none)

Seems to be fine.

I feel like this is a compiler bug; is there any good reason why it 
shouldn't work as expected?

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


[elm-discuss] Task ports: A proposal to make it easier to integrate JS with Elm.

2016-08-13 Thread James Wilson
The problem

ports as they stand are fundamentally incompatible with Tasks. Being backed 
by Cmd's, they are harder to compose. A frustration of mine is that often 
we are directed to "just use ports" when a proper interface to some native 
API is not yet available, but this leads to our Msg types growing and more 
significant changes being required when eventually the proper interface is 
made available.

Also, many JS interop things I find myself wanting to do are fundamentally 
one-shot functions which I expect a result back into Elm from immediately, 
or otherwise just want to compose with other Task based things. Some 
examples that come to mind of one-shot tasks you may want to compose rather 
than use the streaming interface that ports provide:

   - Getting items from local/sessionStorage
   - .. really, most things involving working with the Web API that arent 
   yet implemented in Elm.
   - Embedding JS widgets into Elm elements
   - Using a JS library for doing things like hashing passwords or 
   obtaining some data back from some custom service
   - Interacting with things like Electron for creating apps that can run 
   in the desktop and interact with the filesystem etc.
   

The solution

Task ports. The idea is that these are defined the same way that Ports in 
elm currently are, but they return a Task type rather than a Cmd or Sub 
type. On the JS Side, we attach a function to the Elm app that returns a 
Promise, and on the Elm side we wait for the Promise returned to reject or 
resolve, and marhsall the error or result from the promise into the error 
or result type required by the Task type of the port.

Let's see how this might work:


*Ports.elm:*

port apiSession: Task String SessionId



*Main.elm:*

import Ports
import Json.Decode as Decode
import Task exposing (andThen)


-- get an API session from JS land and make an http request using it
-- given some path and a decoder to decipher the result:
apiRequest : String -> Decoder a -> Task ApiError a
apiRequest path decoder =
  let
headers sessId =
[ ("Content-Type", "application/json")
, ("MyApp-SessionId", sessId)
]


req sessId = Http.send Http.defaultSettings
{ verb = "POST"
, headers = headers sessId
, url = path
}


decodeResponse res = Decode.decodeString decoder -- ...handle error etc
  in
Ports.apiSession `andThen` req `andThen` decodeResponse


*App.js:*

Elm.Main.ports.apiSession = function(){
return new Promise(function(resolve,reject){


var sess = localStorage.getItem("sessionId");
if(!sess) reject("NO_SESSION");
else resolve(sess);


});
}

var app = Elm.Main.fullscreen();




Here, we use a tiny bit of JS to access localStorage and pull out a session 
ID. This function is used whenever the apiRequest Task is performed in Elm, 
and composes nicely into our apiRequest without the need for a complicated 
effect manager or threading a sessionId through everywhere just because we 
need to get it from a Cmd based port.

One of the nice things about this is that there is minimal refactoring to 
do for those things that do eventually receive coverage in the Elm Web API 
- you're just swapping out Tasks for other Tasks. As the Web API will 
always be changing, I think that having a nice way to make JS polyfills 
like this will always have some value, let alone for interacting with 
libraries written in JS that haven't or won't ever be ported to Elm.

Elm would continue to make the same guarantees as with other ports; if the 
task port can't marshall the response back into Elm an error would be 
thrown along the same lines as is currently done via ports.

Summary

- regular ports only let you send data off or receive data back, not both.
- Cmd's and Sub's are not composable
- Task based ports allow you to create a new Task that is backed by JS
- Task based ports allow for better composition and less friction when the 
backing JS is eventually implemented in Elm.

I'd love to hear what people think about this. Perhaps I'm missing some big 
issues with the idea for instance, or maybe it's an awesome idea :) What do 
you all think?

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


[elm-discuss] Chaining and Task with a Port request

2016-08-10 Thread James Wilson
I often feel the same. The "just use ports" argument frustrates me when ports, 
unlike tasks, just don't compose. Eg a hypothetical

readSessionFromLocalStorage `Task.andThen` makeAPIRequest 

Function which, because local storage isn't available in Task form (Yet) turns 
into a 2 stage thing in an update method. If I want to use some custom JS API 
client to make an http request I hit the same wall because I need to remove it 
from my nicely composed chain of tasks and pollute my update function with port 
related back and forth.

Ports and Subs are, however, more like channels than one off events, and so as 
they stand they simply can't compose in the same way as tasks. 

What I'd like is something more like a plugin style approach, where on the JS 
side I can write a function that returns a Promise and hook that into Elm (eg 
set Elm.Main.tasks.mytask to be that function), and then on the Elm side I can 
use that as a task (maybe by declaring 'task mytask : String -> Result String 
SomeOutput'). This would make it far easier to embed JavaScript snippets into 
Elm in a,composable way than ports when you don't want an open one way 
communication channel.

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


Re: [elm-discuss] DOM geometry and getBoundingClientRect

2016-06-30 Thread James Wilson
This is one of my biggest sticking points with Elm; It's something I have 
had to do a number of times at work for things like infinite 
scrolling/manually laying things out based on container dimensions etc. I 
had the same idea of controlling the "big" layouts in Elm by deriving 
things based on window height/width, but when you want to make use of the 
growing number of useful CSS bits like flexbox and the upcoming grid stuff 
rather than reimplementing it partially in Elm, you hit a brick wall.

All that to say, I'll read the post with excitement!

On Sunday, 26 June 2016 17:21:44 UTC+1, Mark Hamburg wrote:
>
> Interesting. I've felt some tension around this as well. I've got an app 
> with a grid of photos that needs to run layout logic based on the width 
> available. Right now, I'm basically deriving that width from the window 
> width but that splits my page layout between Elm and CSS as processed by 
> the browser. If I were to do anything that depended on text measurement, I 
> couldn't do the layout in Elm and would have to get the values back from 
> the DOM. It would be nice to have standard Elm virtual DOM attributes for 
> receiving geometry and scroll position.
>
> Mark
>
> On Jun 24, 2016, at 4:52 AM, debois  
> wrote:
>
> Dear all, 
>
> I just published a blog post on how to get geometry of rendered 
> elements—in particular calling getBoundingClientRect—by constructing JSON 
> decoders for use with Html.Events.on:
>
> https://medium.com/@debois/elm-the-dom-8c9883190d20#.pbwnl4bgl
>
> I needed this for elm-md l. If you 
> have a similar need, you might like the post, and you might find the the 
> elm-dom 
> library  useful. The latter provides 
> some ready-made encoders and a substitute for getBoundingClientRect.
>
> I'd appreciate any comments. 
>
> Obviously, the functionality of reading geometry off the DOM, including 
> calling getBoundingClientRect, should be provided by Core. It doesn't seem 
> to be on the roadmap for the immediate future, though, so in the meantime, 
> I thought you might find the above useful. 
>
> Cheers,
>
> Søren
>
> -- 
> 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.
>
>

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


[elm-discuss] Managing global state in Elm

2016-05-31 Thread James Wilson
In Elm, each component basically has its own internal state (which is 
actually all just a slice of one global model). In my app, I also want 
global state that is independant of any components; for example a 
clientside cache of various API responses (asset details - there could be 
many thousands, user authentication status).

I want any component to be able to call methods that make use of this 
global state. For example, a method to obtain details for items in the 
current view might first look at the global state to see if these items are 
cached. If they arent, the call would provide a Cmd to be issued that gets 
the items (and puts them in the cache), while simultaneously updating the 
state to indicate that they are being loaded (so that the same request 
again from another component doesnt trigger another call to the backend). 
If they are cached, they can be easily returned from there. A first shot at 
a signature might look something like:

getItem : GlobalState -> ID -> Tag -> (GlobalState, Cmd msg)



However we could partially apply functions that exist on some globalState 
instantiation to hdie the initial state being passed in and end up with:

state.items.getItem : ID -> Tag -> (GlobalState, Cmd msg)



The downside of this approach is that I have to thread this state through 
multiple calls that might make use of it, and thread it back up explicitly 
through the update functions to get it back to the top. At the top we'd 
then have something like (excuse any mistakes!):

update msg model = case msg of
   SubMsg m ->
 let (newSubModel, subCmds, newGlobalState) = SubComponent.update m 
model.subModel
 in ({ model | state = newGlobalState, subModel = newSubModel}, Sub.map 
SubMsg subCmds)
   ...


An alternative approach is to hold this global state in an effect manager, 
and so in the app you'd end up using the Cmd/Sub mechanism to ask for 
things from the state and internally initiate API requests to update the 
state as necessary. We'd end up with an API more like:

getItem : ID -> Tag -> Cmd msg


or

state.items.getItem : ID -> Tag -> Cmd msg


where the returned Cmd would either lead to an item being sent to the 
component immediately via a cache (where Tag is a Msg type the component 
knows about) or after it was obtained via some backend. This would make all 
retrieving of state async but seems to simplify the interface (perhaps at 
the cost of more complexity in implementing the effect manager).

Which approach do people think is best for working with global state 
(neither is an option if you have a better way!)? Do you get away with not 
needing this kind of thing (and if so, how)? I'd love to hear back, 
especially from those that have had experience building larger apps in Elm!

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


Re: [elm-discuss] interesting article

2016-05-27 Thread James Wilson
Other bits I learned from chatting to Jean were

- SAM decouples the code that decides what effects to produce from the message. 
This would basically mean splitting the update function into two parts; update 
the model first, and then inspect the new model only to decide which effect to 
run.
- SAM also allows you to completely ignore model updates if you like. Building 
on the above this would mean the function that updates the model retuning a 
book denoting whether it changed anything, so that the function responsible for 
running effect based on the model can be told not to bother.

I think it's all possible in Elm basically, and when I was working on code 
snippets I found times when I really wanted effects based on messages as well 
and it seemed to simplify things, and I struggled to see the concrete benefits 
of forcing a decoupling from the POV of implementing SAM in Elm.

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


Re: [elm-discuss] interesting article

2016-05-24 Thread James Wilson
My impression from a brief discussion on the gitter chat room 
(https://gitter.im/jdubray/sam) about SAM with the creator is that 
basically if you turn:

update msg model = case msg of 
   Increment -> (model + 1, Cmd.none) 
   Decrement -> (model - 1, someEffect)

into

updateModel msg model = case msg of
   Increment -> model + 1
   Decrement -> model - 1

makeActions model =
  if model == 1 then someEffect else Cmd.none

-- the same signature as my last example so it wires
-- into the elm architecture exactly as it would have before:
update model =
  let newModel = updateModel model
  in (newModel, makeActions newModel)

Thereby decoupling the actions we want to perform from the messages/events 
that led the model to be modified, you'd be on the right track for doing 
SAM in Elm.

To quote Jean-Jacques Dubray re the initial snippet:

"When I look at the code you provided, I see a direct line of sight between 
the events and the effects, and that's what SAM is trying to break."

I'm sure that there's more to it than just this, but other bits (eg that 
actions do all the hard work of turning data into something ready for your 
update function (or model.present in some of his examples) rather than the 
update function doing all of the hard work) basically seem to be the case 
already in Elm. I do wonder about the distinction between the component 
state in Elm (what we call the model) and the application wide state (React 
would call this a Store) and how this relates/tallies up with SAM (and more 
generally how best to structure this into an Elm app, though I have some 
thoughts I'm playing with on this). 


On Tuesday, 24 May 2016 19:47:56 UTC+1, Stefan Houtzager wrote:
>
> > What would need to change in the Elm architecture for it to match SAM?
>
> I'm just someone interested in learning elm, so I cannot answer. Are the 
> architects of elm, following these messages, who can? Evan Czaplicki? And 
> is this interesting enough to contact Jean-Jacques Dubray, Evan?
>
>
> Op dinsdag 24 mei 2016 20:30:55 UTC+2 schreef Nick H:
>>
>> Peter's description is very close to how I manage states in my code. It 
>> never occurred to me that it might have its own name; it just seemed the 
>> most natural way to manage states within the Elm Architecture.
>>
>> The model is a union type. The action is a union type. The update 
>> function is just a case statement, so actions that are nonsensical for the 
>> model state can be easily ignored. 
>>
>> As far as I can tell, Dubray's criticism of the Elm Architecture is 
>> summarized in this quote:
>>
>> "That assertion is erroneous. You would be missing a couple of important 
>> parts:
>> - the logic that decides which state you are in so you can properly 
>> compute the view and enable the actions associated to the state 
>> - the next action predicate"
>>
>> The first point of complaint is that both the update and view functions 
>> need a case statement.
>> The second point of complaint is that ... I am not sure. It seems to me 
>> that Elm's Effects are filling the role of Dubray's next action predicate 
>> just fine.
>>
>> These seem like aesthetic differences, so I am sure there is some point 
>> that I am missing. What would need to change in the Elm architecture for it 
>> to match SAM?
>>
>> On Tue, May 24, 2016 at 1:22 AM, Peter Damoc  wrote:
>>
>>> Aligning Elm with TLA+ will make it even more solid from a theoretical 
>>> point of view. 
>>>
>>> SAM sounds very intriguing. I'm wondering if SAM couldn't be implemented 
>>> in terms of TEA using a tagged union as Model.
>>>
>>> something like this:
>>> https://gist.github.com/pdamoc/c96714479d9f531fbc7468d5670ef576 
>>>
>>>
>>>
>>>
>>> On Tue, May 24, 2016 at 8:51 AM, Stefan Houtzager >> > wrote:
>>>
 I am interested in learning elm. I just read an article from 
 Jean-Jacques Dubray. He thinks an alignment with "SAM" would make elm 
 stronger:  
 https://www.infoq.com/articles/no-more-mvc-frameworks#anch133142. 
 Discussions: https://gitter.im/jdubray/sam. 
 What do you think? Might it be interesting to start a discussion 
 with Jean-Jacques Dubray?

 -- 
 Kind regards,

 Stefan Houtzager

 Houtzager ICT consultancy & development

 www.linkedin.com/in/stefanhoutzager

 -- 
 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.

>>>
>>>
>>>
>>> -- 
>>> There is NO FATE, we are the creators.
>>> blog: http://damoc.ro/
>>>
>>> -- 
>>> 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.
>>>