Re: [elm-discuss] Re: Randoms as LazyLists

2017-12-16 Thread Mark Hamburg
One can return a partial function application and it looks just like any other 
function, so in the general case, it can't be garbage collected. This isn't 
special to JavaScript. In fact, JavaScript doesn't support partial function 
application. What JavaScript, Elm, and pretty much any other language that 
purports to be functional does support is capturing values through closure 
creation and because those closures can be returned as values, they need to be 
subject to garbage collection.

Mark

> On Dec 13, 2017, at 2:15 AM, 'Rupert Smith' via Elm Discuss 
> <elm-discuss@googlegroups.com> wrote:
> 
> 
>> On Saturday, December 9, 2017 at 2:13:18 AM UTC, Mark Hamburg wrote:
>> Functions get garbage collected. Otherwise think what would happen every 
>> time you use partial function application or define a function within a let 
>> or other nested context. Because those functions (can) capture values, they 
>> are new values just as much as a list or record or other data value would be.
> 
> Is this something that is specific to the way javascript works? In my 
> experience partial function applications create a continuation, which is a 
> stack frame holding the captured values. Once the function completes the 
> stack frame is discarded, so there is no allocation or GC on the heap. Is 
> this not how Elm would be implemented on webasm and managing its own memory?
> -- 
> 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.

-- 
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] Re: Randoms as LazyLists

2017-12-08 Thread Mark Hamburg
Now if you narrow it to a module scope function and a module scope decoder or 
generator, then no they won't get collected anymore than anything else at 
module scope and hence the reference cycle is immaterial to the GC. But that 
argument would apply just as well to a cyclic list at module scope.

Mark

> On Dec 8, 2017, at 6:13 PM, Mark Hamburg <mhamburg...@gmail.com> wrote:
> 
> Functions get garbage collected. Otherwise think what would happen every time 
> you use partial function application or define a function within a let or 
> other nested context. Because those functions (can) capture values, they are 
> new values just as much as a list or record or other data value would be.
> 
> Mark
> 
>> On Dec 8, 2017, at 1:55 AM, 'Rupert Smith' via Elm Discuss 
>> <elm-discuss@googlegroups.com> wrote:
>> 
>>> On Friday, December 8, 2017 at 5:55:36 AM UTC, Mark Hamburg wrote:
>>> Functions are also heap allocated objects and reference other objects — 
>>> e.g., decoders — just like other objects do.
>> 
>> But presumably functions do not get garbage collected?
>> -- 
>> 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.

-- 
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] Re: Randoms as LazyLists

2017-12-07 Thread Mark Hamburg
Functions are also heap allocated objects and reference other objects — e.g., 
decoders — just like other objects do.

Mark

> On Dec 7, 2017, at 2:32 AM, 'Rupert Smith' via Elm Discuss 
> <elm-discuss@googlegroups.com> wrote:
> 
>> On Tuesday, December 5, 2017 at 5:16:22 PM UTC, Mark Hamburg wrote:
>> If you have a recursive JSON structure to decode, then the decoder either 
>> needs to refer to itself (a cycle) or it needs to generate a new decoder on 
>> each recursive step.
> 
> There is a difference between a function that is recursive and values on the 
> heap that are cyclic. The recursive functions issue seems to be with what 
> order to output compiled javascript code in, when there are mutually 
> recursive functions, as one may not be defined at the point in time when 
> another needs to access it. The cyclic structures on the heap issue, is to do 
> with how to make garbage collection very easy in a language that does not 
> need cyclic structures.
> 
> I think this page is confusing because it discusses both issues at the same 
> time:
> https://gist.github.com/evancz/07436448b7d6c947f21742dab46d1218
> 
> 
> 
> -- 
> 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.

-- 
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] Re: Randoms as LazyLists

2017-12-05 Thread Mark Hamburg
If you have a recursive JSON structure to decode, then the decoder either
needs to refer to itself (a cycle) or it needs to generate a new decoder on
each recursive step.

Mark


On Thu, Nov 30, 2017 at 2:43 AM, 'Rupert Smith' via Elm Discuss <
elm-discuss@googlegroups.com> wrote:

>
> On Thursday, November 30, 2017 at 10:29:42 AM UTC, Rupert Smith wrote:
>>
>> I need to use Decode.lazy to do this. Is that memoized? Is that how
>> decoders can create recursive values? Other than that, I don't see how they
>> could.
>>
>
> Do you need to start with a recursive object in Javascript, then decode
> into Elm using Decode.lazy, to produce a recursive value in Elm?
>
> Approximately:
>
> var rec = { field : rec };
>
> myapp.ports.myport.send(rec);
>
>
>
> type Rec =
>
> Rec
> {
> field : Rec
> }
>
>
> port myport : (Rec -> msg) -> Sub msg
>
>
>
> But of course, that isn't going to compile as ports won't decode tagged
> union types, and you need a tagged union type to define a recursive type.
>
> --
> 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.
>

-- 
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] Re: Randoms as LazyLists

2017-11-27 Thread Mark Hamburg
My bad. Cyclic generator not decoder. Recursive decoders have the same issues.

Mark

> On Nov 27, 2017, at 8:45 AM, 'Rupert Smith' via Elm Discuss 
> <elm-discuss@googlegroups.com> wrote:
> 
>> On Monday, November 27, 2017 at 4:33:57 PM UTC, Mark Hamburg wrote:
>> That page already has an example built using the decoder APIs so unless 
>> something is changing to disallow the creation of such cyclic decoders, 
>> cycles remain. 
> 
> I'm looking at the page. I don't see a cyclic example built with the Decoder 
> API. What am I missing? 
> -- 
> 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.

-- 
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] Re: Randoms as LazyLists

2017-11-27 Thread Mark Hamburg
That page already has an example built using the decoder APIs so unless 
something is changing to disallow the creation of such cyclic decoders, cycles 
remain. The lifting trick still has a cycle at the end — it has to given the 
desire to build something recursive —through the functions and variables even 
if it doesn't end up in some of the data structures.

Specifically, since the lifting is being done to prevent repeated allocations 
of the Random.andThen and we potentially need to pass through the 
Random.andThen logic multiple times, the node must lead back to itself.

Mark

> On Nov 27, 2017, at 2:37 AM, 'Rupert Smith' via Elm Discuss 
> <elm-discuss@googlegroups.com> wrote:
> 
> 
>> On Monday, November 27, 2017 at 7:50:01 AM UTC, Mark Hamburg wrote:
>> P.S. Cyclic structures can be avoided by having the compiler perform a 
>> strongly connected component analysis (e.g., using Tarjan's algorithm) and 
>> disallowing any SCC's that include anything other than function definitions. 
>> In fact, not doing so likely leaves open other cyclic cases and hence 
>> getting rid of Lazy likely does not eliminate cycles and instead just 
>> narrows the cases for which Elm is suitable.
> 
> My hunch is that enough has been done to make cyclic structures impossible, 
> but I have made no detailed analysis to support that. If all data structures 
> are immutable, then references within them have to be created when the 
> structure is first created. The first structure in a cycle to be created must 
> contain a reference to another structure in the cycle, for a cycle to be 
> formed, but as the other structures have not yet been created, this cannot be 
> done.
> 
> I think you should post an example of building a cyclic structure here, if 
> you think it can be done:
> 
> https://gist.github.com/evancz/07436448b7d6c947f21742dab46d1218 
> -- 
> 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.

-- 
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] Re: Randoms as LazyLists

2017-11-26 Thread Mark Hamburg
Example usage of laziness:

We have an expensive layout algorithm which depends both on the data being laid 
out and the view size. Whenever either of these changes, we need to re-run the 
layout algorithm but we would prefer to do the computation only when absolutely 
necessary and only once for any given set of parameters.

What keeps us from using lazy views for this is that the actual view 
instantiation optimizes based on the portion that is visible. If we used the 
view system to memoize the layout independent of the visible range then we 
couldn't introduce a dependency on the visible range below that point in the 
hierarchy.

Mark

P.S. Cyclic structures can be avoided by having the compiler perform a strongly 
connected component analysis (e.g., using Tarjan's algorithm) and disallowing 
any SCC's that include anything other than function definitions. In fact, not 
doing so likely leaves open other cyclic cases and hence getting rid of Lazy 
likely does not eliminate cycles and instead just narrows the cases for which 
Elm is suitable.

> On Nov 26, 2017, at 4:22 PM, N H  wrote:
> 
> Basically, the way things work in Elm is that things exist if people need 
> them -- and can demonstrate the need. So far, there haven't been much need 
> for memoization, outside of the render loop. In fact, the main place where 
> lazy has been used at all has been for generating fuzzy values for elm-test. 
> There, I benchmarked and proved that elm-test is faster _without_ 
> memoization. If you can identify a _real_ problem that you have that needs 
> implicit memoization at the function level (rather than the render level, 
> which elm-lang/virtual-dom provides) then make a case for it.
> 
>> On 20 November 2017 at 11:51, W. Gordon Goodsman  
>> wrote:
>> Oh, I understand the rationale, but it limits the general usefulness of lazy 
>> lists, as certain types of problems need memoization, and without Lazy as it 
>> currently exists there is no way to accomplish it without JavaScript.
>> 
>> Just because the creators of the language don't see a need for it doesn't 
>> mean it doesn't exist.  Even for a lazy list of random numbers, no 
>> memoization means that new random numbers will be computed every time the 
>> list is scanned, meaning the lazy list won't appear to be static.
>> 
>>> On Nov 20, 2017 17:35, "'Rupert Smith' via Elm Discuss" 
>>>  wrote:
 On Friday, November 17, 2017 at 1:25:02 PM UTC, GordonBGood wrote:
 The rational to depreciating these seems to be performance when applied to 
 their limited use in tests and I see that, as I tried to make changes to 
 Lazy that would improve its lack of performance when run on some 
 JavaScript engines that handle internal functions calling functions very 
 poorly.
>>> 
>>> Gordon, it took me a bit of digging through various docs and updates on 
>>> elm-dev to understand it, but... the rational for deprecating elm-core/lazy 
>>> with memoization, is that it allowed recursive structures to be created on 
>>> the heap, and all other ways in which that was possible have been 
>>> eliminated. This is all described here:
>>> 
>>> https://gist.github.com/evancz/07436448b7d6c947f21742dab46d1218
>>> 
>>> It seems to be partly motivated by making garbage collection simpler - 
>>> presumably with WebAssembly in mind. I honestly don't know much of a real 
>>> advantage that is, but it seems that was the trade-off decision that has 
>>> already been made.
>>> -- 
>>> 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/BM_ZmUk-vck/unsubscribe.
>>> To unsubscribe from this group and all its topics, send an email to 
>>> elm-discuss+unsubscr...@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.
> 
> -- 
> 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.

-- 
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] Re: On Intl/CLDR

2017-09-13 Thread Mark Hamburg
One way to maintain language portability to other environments is to make a 
distinction between the language and the libraries. Almost every environment is 
likely to have something special — that's part of what justifies being it's own 
thing. It is entirely reasonable to say that the Basics library should remain 
portable. It is, however, also entirely reasonable to expect that the people 
who did the browser internationalization libraries probably know more about the 
issues than the people likely to write an Elm internationalization library at 
this point in Elm's evolution. If that functionality isn't available somewhere 
else then the library isn't available and that's an issue for that platform not 
for Elm.

Mark

> On Sep 11, 2017, at 10:50 AM, Ian Mackenzie  wrote:
> 
> Exposing window.Intl directly also ties Elm more tightly to the 
> browser/JavaScript environment, which Evan mentioned in that second linked 
> thread that he is trying to avoid:
> 
>> Elm is designed to be 100% independent of JS. It happens to compile to JS 
>> now because that was the right thing to do, but in a decade, I expect we'll 
>> be compiling to something more efficient. There is a small set of "native" 
>> stuff for now, but that means supporting the entire ecosystem on a new 
>> platform is fairly easy.
> 
> So Elm could currently use window.Intl, but that would mean its functionality 
> would have to be replicated exactly if Elm ever compiles to a non-browser 
> environment. Even now that would make life a bit more difficult for people 
> using Elm code within Node applications - it's possible, but you have to do 
> things like hook up a third-party XMLHttpRequest implementation like xhr2. If 
> it's not too hard, it's probably better to reimplement the functionality in 
> pure Elm so that it can be used on any platform that Elm compiles to in the 
> future.
> 
>> On Saturday, 9 September 2017 10:49:31 UTC-4, Vlad GURDIGA wrote:
>> Hey everybody! 
>> 
>> The other day I found myself writing a function to format numbers. The first 
>> question was: What is the right way to format a number? There should be a 
>> standard or something. 樂 Googled a bit and found about the Unicode CLDR 
>> Project. They have a huge amount of structured data, and I surely found the 
>> data I was looking for. 邏
>> 
>> Now, seeing all that data, I thought: Wow! Wouldn’t it be cool to have an 
>> Elm library that’l hold all that? elm-cldr?  Oh, it’d be enormous… What if 
>> I only need number formatting? Oh, I know: elm-cldr-numbers! and 
>> elm-cldr-dates! and elm-cldr-localenames! and… Ooooh yeah!! 鸞
>> 
>> Then I remember that the CLDR website was saying that they provide data for 
>> apps and operating systems. Hm… shouldn’t it be there already somewhere in 
>> the OS? 樂 Googled a bit more and found that browsers already have that as 
>> window.Intl and MDN says it has quite good support, down to IE11. Couldn’t 
>> believe that one, so spun up my Windows VM and pasted a snippet into IE11’s 
>> console: it worked! 
>> 
>> Hm… OK… Now, it’d really be quite cool to build all those elm-cldr-* things 
>> that I imagined, wouldn’t it make more sense to reuse what’s already there? 
>> What would it be like to use that? OK, let’s go native! A couple hours later 
>> I got myself Native.Intl. 
>> 
>> Now, looking at all this I begun wondering what would it be like to have it 
>> in the Elm standard library, and inevitably found Evan’s 2 threads (one and 
>> two) about the philosophy around native in Elm, and I kind of see his point 
>> about keeping Elm high-quality, but how about cases like this where we’re 
>> not talking about JS libraries but about browser’s native APIs like Intl? 樂
>> 
>> It’d probably be not that hard to get that data packaged into a few Elm 
>> libraries, hopefully not-that-large each, but it’d still end up growing the 
>> final app bundles, and probably some compilation time during the hundreds of 
>> refreshes a day that a dev does… So I’m not entirely sure it’s a 
>> constructive idea. 
>> 
>> So although for my little toy-project I can just use Elm native, how about 
>> long-term? What would make more sense? I mean these two options:
>> implement Elm libraries using the CLDR data
>> hope that window.Intl will some day become part of Elm standard library
>> What are some pros and cons? Are there any other options people have 
>> considered? 樂
> 
> -- 
> 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.

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

Re: [elm-discuss] Elm with one message

2017-09-09 Thread Mark Hamburg
If you are going to go that route, then you might as well just send the
function to invoke back around through the message loop. Well, I guess that
breaks the debugger in a way that sending the new model through the loop
does not, but as noted previously sending the model has issues with async
responses.

Mark

On Sat, Sep 9, 2017 at 1:41 AM, Vlad GURDIGA  wrote:

> Hey everybody!
>
> Looking back on this thread, it looks like there are two major issues that
> were brought up: 樂
>
>1. unintended state pre-computation in case of onClick handlers;
>2. accidental resurrection of the pieces of state captured in closures.
>
> From my understanding, it seems like (2.) is not directly related to my
> mostly-messageless approach I initially presented here, and can also happen
> with the standard TEA, so it’s more like something to keep in mind than
> something that is immediately fixable in my code. Noted. ✍️
>
> The (1.) though, seems directly related to my mostly-messageless approach.
> As Peter pointed out, it will get more problematic as the state grows, and
> I wanted to solve it. The solution that Peter proposed was to re-introduce
> messages and update functions, which would have solved the problem by
> moving the state computation to the update function, and so deferring it
> until the click actually happens, as appropriate per TEA. I’ve tried that
>  (to best of my understanding),
> but compared with the mostly-messageless approach, it seems like the amount
> of indirection and code required by messages and update function does not
> justify itself. 樂
>
> One other thought that crossed my mind during this conversation —
> regarding the state pre-computation issue — was to have the onClick
> callback be an actual function that can be invoked when the click happens.
> The thing though, is that because onClick doesn’t have a value to yield,
> its callback is basically a zero-argument function, and so is evaluated
> immediately — which is actually the essence of the issue. 
>
> I worked around that by re-implementing onClick
> 
>  to
> accept a one-argument function instead: 邏
>
> onClick : (String -> msg) -> Html.Attribute msgonClick callback =
> Html.Events.on "click" (Json.Decode.map callback Html.Events.targetValue)
>
>
> …even though the callback argument (an empty string) ends up ignored
> .
> 邏
>
> Problem solved!  
>
> --
> 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.
>

-- 
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 with one message

2017-08-31 Thread Mark Hamburg
Your previous update structure was essentially (ignoring commands and
subscriptions)

type Msg
= Set Model

update : Msg -> Model -> Model
update (Set newModel) model =
newModel


used as something like:

... onClick (Set { model | counter = model.counter + 1 }) ...


The revised approach looks like:

type Msg
= Apply (Model -> Model)

update : Msg -> Model -> Model
update (Apply fn) model =
fn model


used as:

... onClick (Apply (\model -> { model | counter = model.counter + 1 })) ...


The point is that we avoid capturing the model value in the message being
routed around so that we can interleave this message with other
asynchronous responses.

Again, as noted in my earlier message, this is not the Elm way and will be
unfriendly to tools like the debugger but it is valid Elm. It is somewhat
more complicated than the original version but still avoids the level of
indirection associated with messages. It is also more efficient than the
original form in that it at most constructs new function closures rather
than constructing entire new model values for each possible action in the
UX.

Mark

P.S. I was tempted to also include this form in the example:

... onClick (Apply incrementCounter) ...

incrementCounter : Model -> Model
incrementCounter model =
{ model | counter = model.counter + 1 }

But if one did that, one might as well have an IncrementCounter message and
handle it in the update function.



On Thu, Aug 31, 2017 at 11:57 AM, Vlad GURDIGA <gurd...@gmail.com> wrote:

>
> On Monday, August 28, 2017 at 4:01:20 AM UTC+3, Mark Hamburg wrote:
>>
>> One other note: If you don't care about Reactor and the Debugger but do
>> care about async problems, you could get almost the same structure by
>> passing back Model -> Model functions instead of Model values.
>>
>
> Sorry Mark, this sounds cool, but I’m kind of a slow thinker (generally) —
> could you give some pseudo-code to show an example of what you mean? 
>
>
>> Doing so may cause you to receive a visit from the Elm thought police but
>> it is entirely semantically viable within Elm (and it's what I could
>> imagine a lot of other functional languages doing by default).
>>
>> 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.
>

-- 
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 with one message

2017-08-27 Thread Mark Hamburg
One other note: If you don't care about Reactor and the Debugger but do care 
about async problems, you could get almost the same structure by passing back 
Model -> Model functions instead of Model values.  Doing so may cause you to 
receive a visit from the Elm thought police but it is entirely semantically 
viable within Elm (and it's what I could imagine a lot of other functional 
languages doing by default).

Mark

> On Aug 27, 2017, at 1:33 AM, Vlad GURDIGA <gurd...@gmail.com> wrote:
> 
> Hey Mark! 
> 
> Thank you for taking time to look into this! 邏
> 
>> On Thursday, August 24, 2017 at 7:18:44 PM UTC+3, Mark Hamburg wrote:
>> Ignoring the commands and subscriptions part, I think this could be 
>> summarized as being built around having any of the things that would send a 
>> message instead send a new state. This eliminates the level of indirection 
>> of wrapping the desire to change the state into a message and then 
>> unwrapping the message to actually do the state change.
> 
> I haven’t though of it in such a well-formalized manner, but yes, that sounds 
> like it: I eliminate one level of indirection. Or at least at some level, 
> because at the very top there is still a message that triggers the update, 
> even if it’s a super-generic one. 樂
>  
>> It is entirely based on data and hence should be compatible with message 
>> recording for the debugger.
> 
> This looks about right too, as I mentioned in my response to Robin, the 
> debugger does as good of a job as it can with what I’m giving it. 
>  
>> On the other hand, the messages will lack semantic information. (One could 
>> work around that by adding a logging text field that was set when building 
>> the update message but ignored when applying it.)
> 
> Yeah, that’s true. As I’ve mentioned, the reason why I haven’t sensed this 
> problem is because I’m not using the Elm Reactor, because I don’t know how to 
> get ports playing inside it. 
>  
>> Where this would seem to fall down is commands and subscriptions. Those are 
>> going to produce asynchronous results and would risk baking in a stale model 
>> state. This is particularly true for commands. Imagine, for example, wiring 
>> up a tick command that will increment a tick field in the model after five 
>> seconds. Since the command will be constructed to send the single "set the 
>> state" message and since the only model it will have access to is the one 
>> that existed when the command was constructed, it basically becomes a "reset 
>> the state to where it was five seconds ago" command. If subscriptions really 
>> do get rebuilt after every cycle of the update loop, then this isn't a 
>> problem for them but the closure construction for each subscription is an 
>> expense. If they don't get rebuilt — and the code in the initial posting 
>> suggests that instead we're caching a subscriptions value — then as with 
>> commands, it would seem easy to end up with code that resurrects stale 
>> states.
> 
> Hm… I haven’t thought about this aspect of the commands+subscriptions duo, 
> although I think I understand the mechanics. 樂
> 
> So far I think I’m in luck: I have one port (a in/out couple actually) for 
> talking to an external rich text editor, which I expect to be modal. The user 
> clicks a button, the editor opens in a modal dialog, edit-edit-edit, then 
> closes the editor and passes back to Elm, so it’s serialized which means 
> there should not be any other changes to the Elm state while the editor is 
> open. 
> 
> I’m guessing in time, there could come in more things like background sync-up 
> of some kind, and then it’ll be really good to keep in mind these things that 
> you’re mentioning about stale states. 邏
> 
> Thank you! Really good catch! 
> -- 
> 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.

-- 
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 with one message

2017-08-24 Thread Mark Hamburg
Ignoring the commands and subscriptions part, I think this could be summarized 
as being built around having any of the things that would send a message 
instead send a new state. This eliminates the level of indirection of wrapping 
the desire to change the state into a message and then unwrapping the message 
to actually do the state change. It is entirely based on data and hence should 
be compatible with message recording for the debugger. On the other hand, the 
messages will lack semantic information. (One could work around that by adding 
a logging text field that was set when building the update message but ignored 
when applying it.)

Where this would seem to fall down is commands and subscriptions. Those are 
going to produce asynchronous results and would risk baking in a stale model 
state. This is particularly true for commands. Imagine, for example, wiring up 
a tick command that will increment a tick field in the model after five 
seconds. Since the command will be constructed to send the single "set the 
state" message and since the only model it will have access to is the one that 
existed when the command was constructed, it basically becomes a "reset the 
state to where it was five seconds ago" command. If subscriptions really do get 
rebuilt after every cycle of the update loop, then this isn't a problem for 
them but the closure construction for each subscription is an expense. If they 
don't get rebuilt — and the code in the initial posting suggests that instead 
we're caching a subscriptions value — then as with commands, it would seem easy 
to end up with code that resurrects stale states.

Mark

> On Aug 24, 2017, at 8:57 AM, 'Rupert Smith' via Elm Discuss 
>  wrote:
> 
>> On Thursday, August 24, 2017 at 8:47:24 AM UTC+1, Peter Damoc wrote:
>> Without  using Cmds and/or Subs it is an interesting approach if you use it 
>> for managing very small bits of state (the open/close status of a dropdown) 
>> but I'm afraid that it might bring performance problems if you use it for 
>> the entirety of the app. 
>> You basically have to computer all the possible future states of the app. 
> 
> Not so sure about that, as the callbacks seem to only be invoked in 
> continuations?:
> 
> Temei.view data.temei (\v -> c { data | temei = v })
> 
> 
> 
> -- 
> 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.

-- 
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] Re: Would Enums make a good addition to Elm?

2017-08-04 Thread Mark Hamburg
Definitely the big reason from my perspective to make more things
comparable is to allow their use with dictionaries and sets. For that
usage, the comparison could even be compiler dependent (or even execution
dependent) but I'm sure that someone would build code that depended on
properties of some particular implementation.

Mark

P.S. Since this forum likes examples, rather than passing around naked
strings, I pass around type AccountID = AccountID String. This is great
from a type-checking perspective but means that I can't have a dictionary
keyed by AccountID and instead I need to unwrap the value to get the
underlying string. That's not too bad, but I recently had need to fold over
such a dictionary and so found myself faced with either having a function
to force convert a String into an AccountID or storing the original wrapped
AccountID along with the value. Neither solution was particularly pretty —
one because it is a temptation to undermine type-safety and one because it
complicates the dictionary for all other uses.

On Fri, Aug 4, 2017 at 7:54 AM, Richard Feldman  wrote:

> The problem I see with both deriving-esque auto coders (DEAC, patent
>> pending) and comparable union types, is the difficulty of implementation.
>> DEAC's seem like an advanced language feature that will take a while to get
>> into the language.
>>
>
> Having talked to Evan about it, it seems like the design work is what's
> hard. The implementation is actually not a ton of work, apparently.
>
> That said, the design work *is* hard. 
>
> Does a union type require that all fields/members are comparable as well?
>>
>
> I think that'd necessarily be true, yeah. But if union types and records
> are comparable (assuming they hold only comparable types), I *think* you
> end up with something like "functions aren't comparable, nor are
> Kernel-implemented values such as Value, Task, Cmd, and Html, but
> everything else is."
>
>
>> As a reader, how easy is it to tell if a union type is comparable
>>
>
> Probably not easy, would be my guess. It's unclear to me how big of a deal
> that would be though.
>
>
>> and is it obvious when one is lesser than another?
>>
>
> Apparently the way Haskell does this is by using the order of the tags
> (e.g. for type Maybe a = Just a | Nothing, we could say that Just "foo" >
> Nothing because Just came before Nothing in the type declaration), which
> seems fine to use since that ordering is currently arbitrary and
> meaningless. Similarly, record fields could be compared alphabetically by
> field name (since record fields definitionally have no ordering; if you
> needed them to be compared in a certain order, you could use a union type).
>
> Considering the main (only?) reason people want them to be comparable is
> so they can be used in Sets and Dict keys, it doesn't seem hugely important
> how they compare, so long as they can be for purposes of internal data
> structure implementation details. I could be missing something though!
>
> It's not straight forward from a design perspective.
>>
>
> I totally agree! 
>
> --
> 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.
>

-- 
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 `reusable views`

2017-08-04 Thread Mark Hamburg
Wow. If only this stuff were well supported...

On Thu, Aug 3, 2017 at 9:40 AM, Peter Damoc <pda...@gmail.com> wrote:

> Indeed, adding a ResizeObserver polyfill allows for the expected behavior:
> https://ellie-app.com/3VFHVxMsW2ya1/1
>
>
> On Thu, Aug 3, 2017 at 7:18 PM, Mark Hamburg <mhamburg...@gmail.com>
> wrote:
>
>> We watch for resizing using some resize observation JavaScript code —
>> search on ResizeObserver and you can find a number of hits — and feed the
>> values back through a port tagged with the size of the observed entity.
>> Attaching the observer in a virtual DOM is an interesting problem because
>> elements can come in and out of existence based on what happens in the view
>> function. Our solution to that was to mark observed elements with a class
>> and use that to trigger an insanely fast animation and set up an observer
>> to watch for the notification for when that animation runs. This is the
>> sort of thing that leads to me saying "I hate the web."
>>
>> Mark
>>
>> On Thu, Aug 3, 2017 at 3:53 AM Peter Damoc <pda...@gmail.com> wrote:
>>
>>> You could try to use MutationObservers to ferry that information in Elm:
>>> https://ellie-app.com/3VFHVxMsW2ya1/0
>>>
>>> Unfortunately, I don't know enough about them to provide a solution that
>>> would actually monitors their resizing but maybe someone else could.
>>>
>>>
>>>
>>>
>>> On Thu, Aug 3, 2017 at 11:43 AM, enetsee <mthomas...@gmail.com> wrote:
>>>
>>>> Hi,
>>>>
>>>> I have been trying to create a `resuable view` following the structure
>>>> outlined in evanczs `elm-sortable-table`
>>>> <https://github.com/evancz/elm-sortable-table/> and other examples,
>>>> including:
>>>>
>>>>- abadi199s `datetimepicker`
>>>><https://abadi199.github.io/datetimepicker/>
>>>>- thebriticans `elm-autocomplete`
>>>><https://github.com/thebritican/elm-autocomplete>
>>>>
>>>> I was attempting the reproduce the range slider from Palantir's
>>>> BlueprintJS component library (example here
>>>> <http://blueprintjs.com/docs/#core/components/sliders.range-slider>).
>>>> My Elm version is here <https://github.com/enetsee/rangeslider>, with a
>>>> live version in Ellie here
>>>> <https://embed.ellie-app.com/3twhtJfZNvya1/0>.
>>>>
>>>> The Elm version extends the original by allowing the user to specify
>>>> the scale that should be used. The live demo shows both a linear and
>>>> logarithmic scale; the latter is particularly useful when asking users to
>>>> select values which have a heavily skewed distribution (common in finance
>>>> and insurance).
>>>>
>>>> The main limitation of the Elm version compared with the original is
>>>> having to specify a fixed width. The react version seems to use `
>>>> clientWidth
>>>> <https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth>`
>>>> to determine the rendered width of the component and uses that when
>>>> positioning visual elements. As far as I'm aware there is no way to achieve
>>>> this with Elm.
>>>>
>>>> I would really appreciate any pointers on my approach, particularly if
>>>> I have misunderstood the `reusable view` approach, and any ideas on how
>>>> overcome the fixed width limitation mentioned above.
>>>>
>>>> Thanks,
>>>>
>>>> Michael
>>>>
>>>> --
>>>> 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.
>>>>
>>>
>>>
>>>
>>> --
>>> 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+unsubscr...@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.
>>
>
>
>
> --
> 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+unsubscr...@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.


Re: [elm-discuss] Elm `reusable views`

2017-08-03 Thread Mark Hamburg
We watch for resizing using some resize observation JavaScript code —
search on ResizeObserver and you can find a number of hits — and feed the
values back through a port tagged with the size of the observed entity.
Attaching the observer in a virtual DOM is an interesting problem because
elements can come in and out of existence based on what happens in the view
function. Our solution to that was to mark observed elements with a class
and use that to trigger an insanely fast animation and set up an observer
to watch for the notification for when that animation runs. This is the
sort of thing that leads to me saying "I hate the web."

Mark

On Thu, Aug 3, 2017 at 3:53 AM Peter Damoc  wrote:

> You could try to use MutationObservers to ferry that information in Elm:
> https://ellie-app.com/3VFHVxMsW2ya1/0
>
> Unfortunately, I don't know enough about them to provide a solution that
> would actually monitors their resizing but maybe someone else could.
>
>
>
>
> On Thu, Aug 3, 2017 at 11:43 AM, enetsee  wrote:
>
>> Hi,
>>
>> I have been trying to create a `resuable view` following the structure
>> outlined in evanczs `elm-sortable-table`
>>  and other examples,
>> including:
>>
>>- abadi199s `datetimepicker`
>>
>>- thebriticans `elm-autocomplete`
>>
>>
>> I was attempting the reproduce the range slider from Palantir's
>> BlueprintJS component library (example here
>> ). My
>> Elm version is here , with a
>> live version in Ellie here 
>> .
>>
>> The Elm version extends the original by allowing the user to specify the
>> scale that should be used. The live demo shows both a linear and
>> logarithmic scale; the latter is particularly useful when asking users to
>> select values which have a heavily skewed distribution (common in finance
>> and insurance).
>>
>> The main limitation of the Elm version compared with the original is
>> having to specify a fixed width. The react version seems to use `
>> clientWidth
>> ` to
>> determine the rendered width of the component and uses that when
>> positioning visual elements. As far as I'm aware there is no way to achieve
>> this with Elm.
>>
>> I would really appreciate any pointers on my approach, particularly if I
>> have misunderstood the `reusable view` approach, and any ideas on how
>> overcome the fixed width limitation mentioned above.
>>
>> Thanks,
>>
>> Michael
>>
>> --
>> 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.
>>
>
>
>
> --
> 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+unsubscr...@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.


Re: [elm-discuss] Would Enums make a good addition to Elm?

2017-08-03 Thread Mark Hamburg
I thought about whether this was an opportunity to improve error messages
but wasn't sure what the improvement would be. Is it detection that a
previous case already matched everything? Is it specifically noting that
the case involved a variable that shadows an existing variable? Or is this
something better covered with a warning rather than an error about variable
shadowing? For example:

Warning: The pattern variable "foo" shadows the definition at line 342.
Patterns can only use constructors and explicit string and numeric
constants. If you need to compare against a variable, use an if expression.
If you intended to use a pattern variable, you can eliminate this warning
by choosing a different name.

Mark

On Wed, Aug 2, 2017 at 4:27 PM Richard Feldman 
wrote:

> Mark - this seems like a great addition to the error message catalog
> ! I've heard of people
> encountering this too.
>
> Seems like it should be easy enough to detect, and the compiler could
> either provide a concise explanation of what's going on or link to a longer
> explanation.
>
> --
> 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.
>

-- 
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] Would Enums make a good addition to Elm?

2017-08-02 Thread Mark Hamburg
Something like this would probably address a "puzzle" I just resolved
yesterday for one of the engineers on my team. He was testing character
codes and did what one would be inclined to do in most programming
languages and defined names for referencing the values — e.g., leftArrowKey
: Int. He then tried to case on them and was puzzled at why the following
code complained about a redundant pattern:

case keyCode of
leftArrowKey -> ...
rightArrowKey -> ...
_ -> ...


Of course, what's happening here is that the mentions of leftArrowKey and
rightArrowKey in the case statement are each creating new pattern variables
that have nothing to do with the definitions elsewhere of those names. So,
Elm's error message is correct but in this case not helpful. More to the
point, however, the fixes were to either just use the constant values
directly or to replace the case expression with a sequence of if
expressions. Neither of those are particularly attractive. The conclusion
of our exchange was that it would be nice to have some form of named
constants that could be used in case expressions, but adding them would run
counter to Elm's minimalist inclinations.

Mark

On Wed, Aug 2, 2017 at 7:00 AM, Robin Heggelund Hansen  wrote:

> I think most people find that Union Types are a wonderfull thing. I would
> argue that much of the beauty of Union Types comes from using them in a
> case-of statement, having the compiler complain when there is a case one
> haven't covered.
>
> Strings and numbers are not so wonderfull, because they span essentially
> unlimited values, so case-of statements become less valuable.
>
> However, strings and numbers still need to be used in production apps for
> several reasons:
> 1) Union Types is not supported in Json, so one needs to convert to/from
> strings or numbers for communicating with other systems.
> 2) Union Types are not comparable, and so cannot be used as keys in Sets
> or Dicts.
>
> So a server might send me some json where the current user language is
> represented by an Int (0  and 1, norwegian and english) and the current
> game being played is a string ("chess", "checkers", "reversi"). It would be
> great to have some compiler help for these values (say, you forgot the case
> statement for "reversi"), AND it would be great to avoid writing
> encoders/decoders for the union types and converting back and forth several
> places.
>
> Enums would help with this.
>
> The way I imagine this to work is that an enum essentially represents a
> restricted set of String or Number. Once the compiler sees that you're
> working with an enum, it could help you out in case statements. And since
> an enum is just a string, or just a number, they can be used in the same
> places where one would normally use them, like as a value in a select.
>
> One would need a way to check that a string/number matches the values of
> an enum though. Something like `Enum.matches : MyStringEnum -> Maybe (Enum
> MyStringEnum)`.
>
> The one thing I can think of which makes this a bad addition to Elm, is
> that it might be a bit confusing for beginners when to use enum and when to
> use unions... maybe.
>
> Anyway, what do people think of this?
>
> --
> 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.
>

-- 
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] Re: Best practices for designing models in the Elm Architecture - lean or rich?

2017-07-26 Thread Mark Hamburg
Agreed that encapsulation is the way to isolate the engineering trade offs
because that's what this really is about. Ideally, one would never store
values more than once and derived data would always get re-derived. But
that ideal world ignores the cost of computations. Sometimes the cost of
computation is going to be really noticeable if you keep doing it.

So, a simple pattern here as Kasey points out is to put the input values
into a type and then provide an evaluation function for the type to get the
derived value. Maybe the evaluation function just does the computation.
This is great if the computation is cheap. Maybe the evaluation is done
every time the inputs are updated. This is great if we read more than we
write. Maybe writing to the inputs creates a new lazy function that gets
forced when read. This is good if we may have bursts of writes without an
intervening read.

Something like JaneStreet's Incremental library for ML would be cool for
more complex situations but it almost certainly uses mutability in its
implementation. (Incremental feels a lot like many other FRP systems though
it is focused on more of a spreadsheet model  of computation than on an
event flow model.)

And as noted lazy views can help, but only to the extent that the structure
of the data and the structure of the views aligns well. In my case, they
don't. I have a custom layout of a scrolling grid of cells of varying
dimensions. The layout depends on the cell list and the width of the view.
The cells I actually want to instantiate in the view function depend on the
layout and the currently visible range in the scroll. While the cell list
and the width change relatively rarely, the visible range can change
frequently. Since the view function needs to depend on the scroll range,
laziness there can't be the way to avoid running the layout computation.
So, I have explicit dependence logic to update it. What this thread points
out to me is that I should wrap up those dependencies and just those
dependencies in a type to better document the logic.

Mark

On Tue, Jul 25, 2017 at 7:29 AM Kasey Speakman  wrote:

> I don't think it matters one way or another. Whatever you end up finding
> easier to maintain.
>
> What I would do is explicitly represent the BMI as its own module,
> probably with an accompanying data type. In the module operations like
> `updateHeight` and `updateWeight`, you could make sure that the calculation
> is getting rerun. Update would call the module instead of directly setting
> individual properties. Then you have this logic encapsulated and
> centralized.
>
>
> On Monday, July 24, 2017 at 8:23:44 PM UTC-5, Ray Toal wrote:
>
>> This might be an opinion-based question so I can't ask it on
>> StackOverflow. :-)
>>
>> I have a trivial beginnerProgram using the Elm Architecture. It has two
>> text fields (HTML input elements), one for weight and one for height. The
>> onInput attributes of each generate a message. The update function accepts
>> the message and produces the new model.
>>
>> The question is: Should the model (a) consist of the width and height
>> only, or (b) also include the computed BMI (width / height^2)? If the
>> former, I compute the BMI in the view function; if the latter, I would
>> compute it in the update function.
>>
>> Does anyone have a lot of experience with Elm applications that would
>> lead them to believe that keeping models as small as possible and computing
>> derived data in the view function is better than making rich models? I
>> don't have enough experience with Elm to know. I sense that for a problem
>> as simple as mine it really doesn't matter (and I in fact got it working
>> both ways), but as I start scaling up my apps it would be nice to know if
>> there is best practice here (or not).
>>
>> --
> 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.
>

-- 
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] Re: Separating model state structure from the view hierarchy

2017-07-21 Thread Mark Hamburg
Confluence of threads between this one and the question about subscriptions
just made me realize that passing the data model down through the view
model hierarchy on each update to the data model is not the worst thing in
the world from a performance standpoint when you consider that a
subscription-based approach would be collecting up subscriptions from all
of the parts of the view model hierarchy and that would seem like a similar
amount of work unless one cached a lot of the subscriptions in the view
model for faster return.

So, that's good. On the other hand, another thing that subscriptions are
good for that this doesn't answer is as a way of expressing interest.
Imagine a data model with a list of chats and for each chat we have a list
of messages:

chats : DataModel -> Dict ChatID String -- chat id's and names

messages : DataModel -> ChatID -> List Message

We can pass the full data model around. The chat list view can extract the
list of chats. A message view for a particular chat can extract the list of
messages.

For efficiency reasons, we may only want to stay synchronized to the cloud
on the chat list and the current chat. Knowing which chat is current,
however, is really a view-side property. For example, the above API would
be just as friendly to having views into two chats at once. We could have
data model operations to start and stop following a chat. Starting is easy.
We just send the appropriate out message when we construct the view.
Stopping, however, is harder. One of the nice things about subscriptions is
that they go away when the piece of the model doing the subscribing goes
away. The functions we probably really want are something like:

getActiveChats : ViewModel -> Set ChatID

setActiveChats : Set ChatID -> DataModel -> DataModel


We need to call the former routine whenever the view model changes and use
the results to update the data model. Since that will change the data
model, we should then pass the updated data model to the view model causing
an update to the view model thereby looping us back around. To stop the
loop, we need to recognize when something hasn't changed and break the
cycle. That's easy enough but fragile since it would use an equality test
and equality isn't safe to use on arbitrary types. Effects managers don't
have this problem because we don't update the effects manager based on the
main model but rather the effects manager sends messages back to the main
model.

(I'm thinking about this a lot right now because I'm trying to move code to
an API where we need to request rendition URLs based on asset IDs over a
web socket where we are maintaining a synchronized set of assets of
interest between the cloud and the client. Coming up with a clean way to
organize the code is resulting in lots of exploratory sketches.)

Mark

On Fri, Jul 21, 2017 at 9:43 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:

> One argument against the "pass the model to all view functions" approach
> is that it pretty much blows up laziness.
>
> If one ignores that, then one could do something like the following:
>
> * All view-side functions including both update and view receive a global
> context containing the data model. (First argument? Last argument? I'm not
> just throwing this out here. I'm looking for feedback on conventions
> because I've had other places where a global context parameter has come
> up.) This can be in addition to view-side model data as well such as which
> element has focus.
>
> * Commands get replaced on the view side with a construct that can embody
> both operations on the outside world (i.e., traditional Elm commands) and
> operations on the data model. The view side doesn't get write access to the
> data model. The data model is modified in an update fold just as is normal
> for Elm models.
>
> The downsides to this approach include:
>
> * It obscures the true dependencies between the data model and the views.
> The compiler will catch changes (assuming they affect type signatures) but
> the codebase may still feel hard to reason about. That said, one could
> always provide multiple modules for interpreting the data model and one
> could look at the dependices on those modules to reason about the
> relationship of the views to the data model. In other words, it seems icky
> but it might not be in practice.
>
> * The view code can't react to changes in the data model — or at least
> can't do so cheaply. This matters because the view code may want to do
> things like change what it is focused on if an item in the data model goes
> away. Or in the case of the code I'm working on, we have some expensive
> layout logic that depends on he width of the view and the list of items
> displayed in the view. We don't want to run this logic every time we render
> so we need to know when either the width (a view-side

Re: [elm-discuss] Passing whole state to each view function

2017-07-21 Thread Mark Hamburg
Per the other thread discussing this this morning, I don't know that
passing the whole data model to all of the view-side functions is that
horrendous. (We pass around a UXConfig structure in all of our views to
provide access to translation functions amongst other things and the
biggest pain is that I'm not certain that making it he first parameter by
convention was the right choice.) Passing the whole data model feels icky,
but you can document the dependencies using different modules to access
different parts of the data model and you can still keep data model
mutation out of the views by emulating the command mechanism.

That said, there are, definitely friction points where being able to
subscribe to pieces of the data model would be a significant improvement.
See my other message for some examples of these. But the friction is not in
needing to pass the whole data model through the rendering process.

Mark

On Fri, Jul 21, 2017 at 6:55 AM ajs  wrote:

> > However, the downside of doing passing the entire model everywhere is
> that you have to keep the entire model in your head when looking at any of
> your view functions.
>
> This is correct, but how can you avoid passing the whole model to all
> views if the data model isn't structured similarly to your view hierarchy?
> The idea of doing pre-processing on your data into a view-friendly
> structure seems to add overhead and complexity, while also more or less
> duplicating your view structure in two places: the view stack, and the view
> data.
>
> We have found that as apps grow in size, it is unreasonable to couple a
> data model's internal structure to the requirements of a UI, and thus
> passing The whole model is the only valid option for most view functions.
> The exception are leaf nodes down the line that have few or no children, in
> which case they can receive focused inputs only.
>
> --
> 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.
>

-- 
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] Re: Why is the signature of 'program.subs' 'model -> Sub msg' ?

2017-07-21 Thread Mark Hamburg
My understanding is that yes, Elm does this with every update and then the
effects managers have to look at the new subscriptions and compare them to
the old subscriptions. I would love to hear that my understanding is wrong
because while this isn't bad if you have just a few subscriptions, it seems
like potentially a lot of overhead if you have a lot of subscriptions.

One could envision subscriptions being implemented more like views in which
there would be a differ that would generate patches to send to the effects
managers and there would be a subscription equivalent to Html.Lazy that
would cut off a lot of the computation when nothing had changed. This would
probably make frequent update to subscriptions less scary computationally
but it isn't how things are done.

Finally, you haven't asked the other subtle question brought on by dynamic
subscriptions: if you stop returning a subscription, are you guaranteed
that you won't receive any messages targeted to that subscription or are
you only guaranteeing that no more messages will be queued or even weaker
are you only letting the effects manager know that you aren't really
interested any more?

Mark

On Fri, Jul 21, 2017 at 6:55 AM Vasily Vasilkov 
wrote:

> Does it mean that Elm runtime creates and cancels subscriptions on the fly
> (for  every model change)?
>
>
>
> On Mon, Jul 17, 2017 at 6:19 PM +0400, "Marek Fajkus"  > wrote:
>
> Sometimes you don't need subscriptions if you're in some state. For
>> instance, if you have game and subscription to say mouse position you can
>> subscribe to Mouse.position only when a user is in play state and avoid
>> subscription in game menu.
>>
>> --
>> 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.
>>
> --
> 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.
>

-- 
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] Re: Separating model state structure from the view hierarchy

2017-07-21 Thread Mark Hamburg
One argument against the "pass the model to all view functions" approach is
that it pretty much blows up laziness.

If one ignores that, then one could do something like the following:

* All view-side functions including both update and view receive a global
context containing the data model. (First argument? Last argument? I'm not
just throwing this out here. I'm looking for feedback on conventions
because I've had other places where a global context parameter has come
up.) This can be in addition to view-side model data as well such as which
element has focus.

* Commands get replaced on the view side with a construct that can embody
both operations on the outside world (i.e., traditional Elm commands) and
operations on the data model. The view side doesn't get write access to the
data model. The data model is modified in an update fold just as is normal
for Elm models.

The downsides to this approach include:

* It obscures the true dependencies between the data model and the views.
The compiler will catch changes (assuming they affect type signatures) but
the codebase may still feel hard to reason about. That said, one could
always provide multiple modules for interpreting the data model and one
could look at the dependices on those modules to reason about the
relationship of the views to the data model. In other words, it seems icky
but it might not be in practice.

* The view code can't react to changes in the data model — or at least
can't do so cheaply. This matters because the view code may want to do
things like change what it is focused on if an item in the data model goes
away. Or in the case of the code I'm working on, we have some expensive
layout logic that depends on he width of the view and the list of items
displayed in the view. We don't want to run this logic every time we render
so we need to know when either the width (a view-side property) or the item
list (a data-model property) changes. The non-cheap solution here is
broadcasting the new data model (or the old and the new data model) through
the view hierarchy on roughly every data model update.

Another solution would be to manage the data model via an effects manager
thereby allowing it to expose both commands for changes and subscriptions
for updates. This seems ideal for the scenario you've presented. The
problem is that effects managers cannot, AFAIK — please correct me if I'm
wrong, use other effects managers, so taking this approach cuts your data
model code off from the standard web sockets and HTTP implementations.

To get any deeper into Elm-based approaches, I think we would need to know
more about Re-Frame so any further details you can supply or point to would
be welcome.

Mark

On Fri, Jul 21, 2017 at 8:29 AM Martin Norbäck Olivers 
wrote:

> Hi!
> We discussed this on the slack the other day, right?
> Let me just get this straight, the Re-Frame solution depends on functions
> having access to a global "db" object or similar (that corresponds to the
> Elm model)?
>
> How is that conceptually different than passing the model as a parameter
> through the functions? Any function can access any part of the state by
> subscribing in Re-Frame, just as it can access any part of the state by
> accessing the passed-through model in Elm.
>
> I just want to know what more this gives than avoiding the boilerplate of
> passing the model through.
> Btw, Elm has pure functions so implementing this straight-off is not
> possible.
>
> Regards,
>
> Martin
>
> Den fredag 21 juli 2017 kl. 15:55:42 UTC+2 skrev ajs:
>>
>> I had an interesting discussion with several members on the #beginners
>> channel on Slack. It was suggested I post this out to the larger community
>> for input.
>>
>> As a quick background, I'm a professional Clojurescript developer for
>> many years, and have been through the early days of React (when it was just
>> wrapped as Om in Clojurescript), and then Reagent, and then the most
>> versatile and structured tool, Re-Frame, which has emerged as a leading
>> model of UI <-> Model interaction. I am now looking seriously at Elm on my
>> company's behalf and we are testing a prototype for a component in it.
>>
>> The Elm Architecture is often compared to Redux and Re-Frame. The overall
>> flow is similar, however there is a particular problem that plagued
>> Clojurescript's Om in the early days that was eventually worked out in
>> Re-Frame and in later versions of Om. This problem, however, does not
>> appear to have a solution in Elm, and I wish to outline it here. It is a
>> common problem that occurs in modelling a UI in a complex SPA, anything
>> truly non-trivial.
>>
>> The way the Elm Architecture works, and in the early Om, is that you have
>> a single piece of state that acts as the truth for your app, and then you
>> have view functions that receive parts of this state (or all of it), and
>> then they call children view functions and pass along parts of the state
>> they received. I have 2 

Re: [elm-discuss] Re: State of CSS in Elm

2017-07-07 Thread Mark Hamburg
The latest version of the library does look very nice. I'm just starting to
use it for prototyping some new cases.

A skim suggests that the only way to use laziness is to drop in and out of
HTML. Is that a correct read or did I miss something?

Mark

On Wed, Jul 5, 2017 at 10:38 AM, Matthew Griffith 
wrote:

> Hey Greg,
>
> Thanks :)
>
> The most helpful thing you can do is try out the library if you get the
> chance, and let me know your experience on the #style-elements channel on
> slack
>
> As for drawing comparisons, that's definitely going to be part of the
> focus of the visual guide I'm working on.  My current plan is to have a
> "cookbook" of common layout recipes and how this library solves them, as
> well as some explanation as to *why* this approach makes sense compared
> to the common approach.
>
> I'll post here when it's done.
>
>
>
>
> On Wednesday, July 5, 2017 at 12:47:00 PM UTC-4, Greg Coladarci wrote:
>>
>> Hey Matthew,
>>
>> Just wanted to also say that this video was fantastic. As someone who has
>> spent 10 years w/ my feet firmly planted in the "style concerns don't
>> belong in your template" it is still very hard for me to get used to this
>> idea, but I *want* to get there. To some, I fear these concepts will be
>> like bringing back the  tag. I think it'll help your project
>> immensely (and therefore Elm as a whole) to get ahead of this as I can tell
>> from your opening remarks that you are coming from a place of deep
>> understanding of the history of the space. You touched on this when you
>> phrased things like "this is like what you'd use media queries for, but..."
>> - I think comparing "current" "accepted" real world solutions to common
>> problems (SASS, Media Queries, Compass?, etc) w/ the equivalent in your
>> library could help bring even more people over and help the greater cause.
>>
>> For example, I don't want my engineers to say "Bad" but I would mandate "" over
>> "" and then using a dedicated style in my sheet
>> for this one off ID. So here I am putting styles in my markup "breaking the
>> rule". To some degree, your library is taking that to an absolutely extreme
>> w/ some incredible promises of reliable layout. I look forward to following
>> the progress and would love to help if there's anything I can do on this
>> front.
>>
>> On Wednesday, July 5, 2017 at 4:15:31 AM UTC-7, Matthew Griffith wrote:
>>>
>>> Hi Berry,
>>>
>>> Good to hear!
>>>
>>> Yeah, the video was just released a day ago, so not surprised you didn't
>>> see it until then :)
>>>
>>> I'm putting together a website that will serve as a live example,
>>> explanation of concepts, and a visual guide, just need the time to actually
>>> finish it.  I'll post in elm-discuss and /r/elm once it's done.
>>>
>>> I have seen GSS/Cassowary and have definitely thought about adding some
>>> sort of constraint based logic to style-elements, but we'll see.  There are
>>> a few things for the library that I'm focusing on right now(like the
>>> guide), but once they're done, I'm sure constraints will come up :)
>>>
>>> If you check out the library, I highly recommend joining the
>>> #style-elements channel on the elm slack.  I'm generally there to answer
>>> questions.
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Wednesday, July 5, 2017 at 6:32:39 AM UTC-4, Berry Groenendijk wrote:

 Hi Matthew,

 I have looked at style-elements before in the package repository. But,
 by just reading the package documentation I struggled to fully understand
 or appreciate this library. But, your presentation at Elm Europe 2017 (
 https://www.youtube.com/watch?v=NYb2GDWMIm0) was very clear and
 instructive. It made me realize this was exactly what I was looking for.
 Elm started out with an "element" library way back in version 0.14 (or
 something). Then Elm switched to the HTML Library. And style-elements looks
 like a sort of merging between these two concepts. Style-elements is
 exactly the kind of development that attracted me to Elm in the first
 place. Elm is "javascript done better" and style-elements is "HTML+CSS done
 better".

 My advice: please make a reference in your package readme to your Elm
 Europe presentation. And/or link to a small website that explains the why
 of this library and thus explains the concepts behind your library and use
 examples that show how to use the library. Basically, turn your Elm Europe
 presentation into a website explaining your library and put a link to this
 website in your package.

 And a question: have you looked at Cassowary.js and implementations
 like GSS? See: http://overconstrained.io/. At first glance
 style-elements is currently not a constraint based layout engine. But, it
 feels like style-elements and constraint based layout are a natural fit.
 What is your opinion on this?

 Thanks and I will start using your library.

 Berry


Re: [elm-discuss] Passing whole state to each view function

2017-06-25 Thread Mark Hamburg
Thanks for the term "referentially equivalent". It's a nice counterpart to
"referentially transparent". (Long-time LISPers would know these as "EQ" v
"EQUAL".)

Mark


On Sat, Jun 24, 2017 at 8:52 PM, Max Goldstein 
wrote:

> Great points, Mark!
>
> I came across this r/elm thread
>  and
> they conclude that Html.lazy only skips a computation if the argument is
> *referentially* equivalent to some previous value. If true, this would
> invalidate the *toView* approach in Mark's first post on this thread.
>
> I think this suggests having viewstate already split out in the model,
> i.e. a record or records. Then you pass each smaller record to a view
> function. But the idea of defining your model in a way to make your view
> functions more performant is not a pleasant one.
>
> --
> 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.
>

-- 
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] Passing whole state to each view function

2017-06-22 Thread Mark Hamburg
Actually, Html.Lazy also saves the differ the task of comparing the
subtrees when laziness saves us from work, so it can be a big win if UI
updates are a significant chunk of the work.

That said, Max is correct that memory allocation for new structures is also
a cost and is something to be avoided. (Functional programming loves to
allocate memory...)

So, the basic rules of thumb are:


   - If you have a big model pieces of which get rendered in various
   combinations by other code, try splitting those pieces out and using the
   record extension syntax to access just the fields needed while avoiding the
   cost of building a separate record.
   - If you only need a little bit of information from the model for a
   subview, you can just extract it and call the subview function and avoid
   the record syntax overhead.
   - If your model is structured in a way that makes it easy to keep valid
   but harder to draw, that's probably a good trade off — make impossible
   states impossible and all that — but may call for using an intermediate
   structure between the model and the actual view code. (See Charlie Koster's
   piece on "selectors".)
   - Laziness can be a big win for both render and diff times with complex
   views BUT you need to be aware of how the lazy logic works and not hand it
   data that isn't likely to use the same data instances from render to render.
  - Laziness can be good as one approaches the leaves and the data
  becomes more primitive.
  - Laziness can be good near the top if there are large chunks of your
  model that won't be changing from cycle to cycle.
  - Laziness gets a bit tricky in between these two because it can be
  useful to build intermediate structures while rendering and those break
  laziness.
   - Experiment with the signature to your view functions. The basic idea
   of a view function is that it takes some data and returns some HTML. For
   example:
  - Config records can handle views that need more set up (but you will
  likely want to move them out to module scope for performance if possible.
  - If you have theme support in your UX, it may be useful to pass the
  theme down to all view functions that care as a separate parameter.
  - Sometimes it is useful to have view functions return lists of HTML
  nodes rather than a single node.

Mark

On Thu, Jun 22, 2017 at 1:46 PM, Max Goldstein 
wrote:

> To state Mark's point clearly: if your view depends on only a small number
> of the model's fields, then you are likely to rerender the view only when
> some other fields changed, which is unnecessary.
>
> That said, you might not be at the point of needing laziness for
> performance. In particular, allocating and copying a new record has a cost
> of its own, and you'll have to measure to find if it's worth the lazy call
> to the function. Important: because of the virtual DOM, Html.lazy only
> saves you the overhead of calling the view function, both its logic and
> creating the virtual DOM. If the view function returns virtual DOM that
> matches the existing, real DOM, no DOM manipulation is performed, and
> that's the real performance win.
>
> So, it is definitely simpler and easier, and possibly no less performant,
> to pass the model directly to the view. It would be nice if we could use
> the type system to limit which fields of the model the view can see, so we
> can isolate it better for understanding and testing. Fortunately there is a
> neat trick that does just that:
>
> view : { r | foo : Int } -> Html Msg
> view {foo} = ...
>
> This function accepts any record which has a foo field of type Int. If
> your model has that field, it can be passed in, but no other fields in the
> model are available to the view function.
>
> --
> 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.
>

-- 
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] Passing whole state to each view function

2017-06-22 Thread Mark Hamburg
Also note that while the approach of transforming your model into a more
view-specific data structure — e.g., extracting the pieces of interest —
can be a great pattern in terms of code clarity, it works against using
Html.Lazy. For background on the pattern, see Charlie Koster's piece on
selectors and view models:
https://medium.com/@ckoster22/upgrade-your-elm-views-with-selectors-1d8c8308b336
.

Concretely, structuring your code as:

toViewData : Model -> ViewData

displayViewData : ViewData -> Html Msg


and thence

view : Model -> Html Msg
view =
toViewData >> displayViewData


works well — particularly if it allows for putting the view function into
its own module where you might feel more free about doing lots of exposes
for Html, Css, etc. However, it also means that the view function and any
pieces thereof cannot effectively be lazy based on the ViewData it is
passed because the ViewData instance will be new each time (even if it is
actually equal to the previous value) and Html.Lazy does a naive (also
known as fast) equality check based on instance identity.

If you know how Html.Lazy works, this issue is perhaps obvious in the code
above, but as view functions get bigger to deal with more complicated views
or moves to its own module, I've seen cases where developers think "this is
an obvious place to put in some laziness" only to have it simply result in
more work for the view system.

Why do we even care about laziness? Because it's the functional programming
answer when engineers from other backgrounds say "You re-render the whole
model on every change? Isn't that vastly less efficient than just updating
the parts of the view that changed?" It's also part of how Elm gets the
performance numbers that it gets on UI benchmarks.

So, great pattern. Use with caution.

Further notes below on laziness. Read if interested.

Mark

P.S. The way to get laziness in the above is:

view : Model -> Html Msg
view model =
Html.Lazy.lazy doView model

doView : Model -> Html Msg
doView =
toViewData >> displayViewData

We need to specifically define doView because every time we execute >> we
get a new function instance which will then fail the laziness match.

The unfortunate thing here is that if the model contains pieces that don't
directly affect the display — e.g., a queue of messages to send — then the
laziness also depends on those pieces of the model. Part of the appeal of
the ViewData intermediary is that it projects that stuff away.

P.P.S. Over-engineered solution (though it would also help subscriptions as
well): The implementation strategy that makes Html.Lazy work could probably
be extended to a general recompute pattern with laziness. The basic idea is
that while evaluating the tree, you can look at the previous tree and see
whether a lazy node has the same inputs as before and if so just use the
answer from before. You need a small imperative piece that deals with the
update from one tree to the next but that can live in the runtime.
Something like this could immediately address the potential issue that
calculating subscriptions after every update could be rather expensive
depending on the size of the model and the number of subscriptions. For the
discussion above, one would formalize the notion of view data — with
identity being the simple implementation for converting the model to view
data — and then do a "smart" re-computation of the view data as the first
step in rendering the view.

One could probably even do this without changing the runtime model with
just the addition of a native module akin to the Lazy module. Let's call
that module Cache and give it an interface like the following:

eval : Cache a b -> (a -> b) -> a -> b
-- (eval cache fn a) evaluates to an equivalent value as (fn a); it may
use and/or update the supplied cache

eval2 : Cache2 a b c -> (a -> b -> c) -> a -> b -> c
-- (eval cache fn a b) evaluates to an equivalent value to (fn a b); it
may use and/or update the supplied cache


etc

Caches are mutable but opaque state and their specification should mean
that the only visible effect from them should be reduced code execution.

Enhancements around deeper — but non-exception-throwing -- equality checks
could also help drive things back to states that will match with the
laziness match detectors.

If anyone writes this, let me know and I would be happy to start using it.
:-) If I get there first, I'll say so though obviously this would not be
available via the Elm package manager because of the need to access Elm's
internal data structures.


On Wed, Jun 21, 2017 at 9:47 PM, Aaron VonderHaar 
wrote:

> There is no performance penalty to passing the entire model to all nested
> view functions.  Elm will simply pass the reference to the object around,
> so the performance of passing the entire model vs passing just the
> necessary parts should be equivalent.
>
> However, the downside of doing passing the entire model everywhere is 

Re: [elm-discuss] Re: elmq - is it a worthwhile abstraction or not?

2017-06-16 Thread Mark Hamburg
The. Config parameter to generate messages is much like the out message 
approach in that essentially the child is listing off things that it either 
can't handle itself or that it doesn't actually care about but wants to let the 
parent know about. For example, a sign in module when finished may just want to 
say "We're signed in now!" or for that matter "The user canceled." Config 
basically is a way to say "I may need to send these messages to you, please 
tell me how to send them." Out messages list the things that will be returned 
and presumably the parent code will case over them.

As for which to choose, it probably comes down to a question of which approach 
does a better job of having manageable boiler plate. The out message approach 
does make me feel like I'm writing the same code over and over again,  but it 
does follow a well defined pattern so it's not like I'm having to think hard 
while getting the structure in place. I assume that the config approach 
involves similar but different "boiler plate" in that each child response needs 
its own parent message and implementation in the update function.

Another option for something like the sign in case is that the parent just 
queries the child after every update. "Are we signed in yet?" For some cases, 
this works well but it also means that children may need to store more state. 
For example, it's a lot easier to send a "close me" message to the parent in 
response to the close box being hit than it is to store a Boolean "I'm closed 
flag" and have the parent query it's status to discover that the modal child 
should be closed.

All that said, I think elmq is really interesting for the case where the 
interaction isn't hierarchical. For example, model hierarchy might reflect the 
presentation which might be relatively different from the model needed to talk 
to the server. It's a pity it can't be typed. Lacking type support, it's 
interesting to think about it as being analogous to talking to a web server in 
the encode/decode process. Following that line of reasoning, however, leads to 
wanting a way to send a message and get a response delivered only to the sender 
rather than broadcast to every part of the app talking to that internal server.

Mark

P.S. To avoid triples in return values from update functions and corresponding 
complexity in support libraries, I folded commands into out messages. 
Conceptually, they are the same thing — requests for an effect beyond the 
bounds of the model being updated. This does, however, mean that every update 
has to include command forwarding logic as part of its out message processing.

> On Jun 16, 2017, at 8:47 AM, Charles Scalfani  wrote:
> 
> I authored a library that handles this problem pretty simply and the 
> abstraction is definitely worth it as I am writing backend Elm and we have 
> complex libraries that are 6 levels deep. You can check it out at: 
> https://github.com/panosoft/elm-parent-child-update
> 
>> On Friday, June 16, 2017 at 4:13:09 AM UTC-7, Rupert Smith wrote:
>>> On Friday, June 16, 2017 at 12:04:48 PM UTC+1, Rupert Smith wrote:
>>> As above, make my own ElmqMessage type and pull the routing logic out of 
>>> the effects module. This would result in a message router that retains the 
>>> dynamic routing capability, should anyone ever need such a thing.
>> 
>> This would actually be better - one of the problems elmq has is that the 
>> internal representations of Cmd and Sub in an effects module need to be 
>> declared in it as a particular concrete type:
>> 
>> https://github.com/rupertlssmith/elmq/blob/master/src/Elmq.elm#L2
>> 
>> As the consumer of the module cannot vary this type with type parameters, it 
>> settles on passing everything as a Json.Encode.Value. This means that the 
>> message router is not as strongly typed as it could be - the compiler cannot 
>> make sure that when I pass a chat message of type String, the receiver of 
>> that message is also  expecting a String and not say an Int.
>> 
>> Doing it all outside of an effects module with a type of 'ElmqMessage a' 
>> would allow stronger guarantees to be enforced.
> 
> -- 
> 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.

-- 
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] Re: Implementing a protocol on top of WebSocket: should I build a effect module ?

2017-05-16 Thread Mark Hamburg
The Phoenix code is interesting but it is not an example of one effects manager 
using another. It bypasses the web socket effects manager and talks to the low 
level API.

Mark

> On May 16, 2017, at 4:38 PM, Oliver Searle-Barnes  wrote:
> 
> You might find https://github.com/saschatimme/elm-phoenix useful to look at, 
> it's an effects manager phoenix channels built on top of the websocket 
> effects manager.
> 
>> On Tuesday, 16 May 2017 15:30:18 UTC+1, Christophe de Vienne wrote:
>> Hi everyone, 
>> 
>> I am attempting to implement the pub/sub NATS (https://nats.io) protocol 
>> on top of the WebSocket API as a TEA component. 
>> 
>> I have a hard time finding an API for subscriptions: for each 
>> subscription some context must be kept, a unique subscription ID 
>> generated and in some case a unique reply subject too, and I would like 
>> each subscription to generate custom messages for the component which 
>> made it. 
>> 
>> I suspect it would be a lot more natural with an effect module, with 
>> which I could (hopefully) write, in any part of the application: 
>> 
>> subscriptions : Model -> Sub Msg 
>> subscriptions model = 
>> Nats.Subscribe model.endpoint "some.subject" MyMessage 
>> 
>> or, for req/rep (a pub + a short-living sub expecting a result): 
>> 
>> myrequest : Model -> Cmd Msg 
>> myrequest model = 
>> Nats.request model.endpoint "a.request.subject" MyReply 
>> 
>> 
>> Another difficulty I have is that in some cases I need to send 2 or 3 
>> messages through the websocket, in the right order, but WebSocket.send 
>> returns a Cmd. So I have to concat the 3 commands in 1 message, which 
>> works but oblige 
>> 
>> Am I wrong being tempted by using an effect module for this kind of module ? 
>> If so how can I mimick such an API with a TEA approach  ? 
>> If not is there any documentation I can read to get familiar with them ? 
>> 
>> Is there any existing module that does this kind of thing for another 
>> protocol ? 
>> 
>> Thanks! 
>> 
>> -- 
>> Christophe de Vienne 
> 
> -- 
> 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.

-- 
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] Implementing a protocol on top of WebSocket: should I build a effect module ?

2017-05-16 Thread Mark Hamburg
I've been looking at similar issues for protocol handling.

As I understand it — and I would welcome someone pointing to evidence otherwise 
— effects modules can't use other effects modules. That means that if you want 
to use web sockets, you either don't use some of the services that effects 
modules provide (subscriptions, easy routing for commands) or you build your 
own effects module possibly cutting and using the low level web sockets module 
used by the web sockets effects module. (What's the thinking on whether that's 
a recommended choice? My inference from the name "low level" is "please stay 
away", but maybe that inference is mistaken.)

If you don't want to go the low-level route, then you need to build something 
on top of the existing web sockets effects module.

For command-like behavior, this is relatively straightforward. For example, you 
can change the return value from update functions from ( Model, Cmd Msg ) to ( 
Model, Operation Msg ) where Operation is a type that mirrors and subsumed Cmd 
while also allowing your top level code to route requests to your protocol 
handling module and to route responses back to the rest of your code. In some 
sense, this is what effects managers are doing. They just do it with linguistic 
and runtime support so that you don't have to wire things up.

Subscriptions can be handled in the same way. You can replace the subscriptions 
function call with a call to something like `observations` and get back a 
similar structure that subsumes regular subscriptions while also allowing your 
top-level code to route items meant for your "user-mode effects manager" to 
that manager. At this point, however, you will need to figure out how often to 
call `observations`. My understanding is that Elm calls this after every update 
but I don't think the documentation says.

In other words, if you want to build an effects manager like piece of code but 
don't want to write it as an effects manager — because, for example, you want 
to use other effects managers — you can do so. You just need to build parallels 
to the standard Elm infrastructure.

You also need to reconcile yourself if this is concern to the fact that your 
user mode effects manager will be storing functions in the model to remember 
how to route responses. If it's any solace, that's what regular effects 
managers do as well, so I wouldn't feel too bad about it.

But maybe someone can render this whole message moot by saying "just write an 
effects manager because there is no prohibition on one effects manager using 
another". Of course, that would also be easier with documentation about how to 
write an effects manager, but that's a different subject.

Mark

> On May 16, 2017, at 8:32 AM, Christophe de Vienne  
> wrote:
> 
> 
> 
>> Le 16/05/2017 à 17:17, Christophe de Vienne a écrit :
>> Thank you for the feedback.
>> 
>> I am still trying to find a non-effect based API. Did not find anything
>> satisfying so far.
>> 
>> The WebSocket.LowLevel module is interesting for send batches, but my
>> main issue is how to associate a custom message translator to each
>> subscription in a global protocol state.
> 
> Plus the WebSocket module provides very useful behavior I would prefer
> not to reimplement.
> 
>> 
>>> Le 16/05/2017 à 17:02, Aaron VonderHaar a écrit :
>>> Hi, I haven't played much with WebSockets, but I have been building a
>>> protocol on top of HTTP.  I haven't yet run into an issue that made me
>>> think to try an effects module.
>>> 
>>> Instead of having custom subscriptions, my package has an `update`
>>> function that takes any msgs resulting from its commands and returns
>>> some appropriate stuff (in my case, that is an optional output value
>>> that the caller can do something with, and also another Cmd to run).
>>> 
>>> For the Cmds, I do have to use the Tasks portion of the HTTP API so that
>>> I can compose and chain things together (though I do in the end return a
>>> Cmd for most functions in my protocol's API).  For WebSockets, I see
>>> there's 
>>> http://package.elm-lang.org/packages/elm-lang/websocket/1.0.2/WebSocket-LowLevel
>>> which provides Tasks instead of Cmds, so it's likely you could use that
>>> for what you need.
>>> 
>>> I don't know if those things will address all the needs of your
>>> WebSockets protocol, but those approaches have worked for what I've been
>>> building.  (Sorry, it's not open-source, so can't share the code.)
>>> 
>>> --Aaron V.
>>> 
>>> On Tue, May 16, 2017 at 7:30 AM, Christophe de Vienne
>>> > wrote:
>>> 
>>>Hi everyone,
>>> 
>>>I am attempting to implement the pub/sub NATS (https://nats.io) protocol
>>>on top of the WebSocket API as a TEA component.
>>> 
>>>I have a hard time finding an API for subscriptions: for each
>>>subscription some context must be kept, a unique subscription ID
>>>generated and in some case a unique 

Re: [elm-discuss] Platform.Cmd.batch executes commands in reverse order

2017-05-13 Thread Mark Hamburg
What you can do is emit the commands in two batches. The first sends the
time critical operation(s) and sends a trigger message back to send the
second batch of commands. Note that you can use Cmd.batch to send multiple
commands on the delayed path:

type Msg =
Later (Cmd Msg)

update : Msg -> model -> ( model, Cmd Msg )
update msg model =
case msg of
Later cmd -> ( model, cmd )

later : Cmd Msg -> Cmd Msg
later cmd =
Task.succeed cmd
|> Task.perform Later


Mark

On Fri, May 12, 2017 at 2:50 PM, 'Rupert Smith' via Elm Discuss <
elm-discuss@googlegroups.com> wrote:

> On Friday, May 12, 2017 at 4:53:19 PM UTC+1, Peter Damoc wrote:
>>
>> The execution of a Cmd.batch list of commands has not ordering guarantee.
>>
>
> I suspect that whilst there is no ordering guarantee given, the actual
> implementation probably does a 'foldr' executing them in reverse order.
> This behavior seems very consistent.
>
> In theory they could be executed in parallel and non-deterministically. In
> reality its javascript on the browser, which is single threaded, so there
> is no concurrency.
>
> --
> 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.
>

-- 
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] Re: Moving on

2017-04-30 Thread Mark Hamburg
On Apr 30, 2017, at 8:43 AM, Max Goldstein  wrote:
> 
> Fourth, web components were briefly mentioned. Richard gave a talk on these 
> last year and it seems like everything you need already works.

Specifically, on this, no. The virtual DOM API does not make the sort of 
specific commitments one would need in order to know that a web component with 
its own state would not get accidentally destroyed and recreated rather than 
preserved. The code that works today just happens to work because the virtual 
DOM implementation just happens to do certain things that just happen to work 
out right. An example of the sort of guarantee that would resolve this would be 
"keyed nodes always preserved keyed child identity on updates provided you 
don't assign the same key to multiple children". That comes with caveats about 
what won't work and you have to make sure the path is stable all the way up the 
DOM and not just at the component, but if you obey the rules, it promises that 
something will work and keep working. Html.Keyed makes no such guarantee and as 
I recall when I last looked at the code it didn't look like the implementation 
would be likely to support such a guarantee.

On the broader issue, Elm is free code and it does what it does and being free, 
people have no right to ask for anything more. But similarly people need to 
figure out whether the benefit they are getting is valuable enough to stick 
around v some of the other options that have been bandied about on this thread 
such as moving to other languages or forking Elm (thereby essentially creating 
another language). The talk here does not in general seem focused on going 
elsewhere but rather on what sort of changes in process and policy would quell 
the concerns. Remember that this thread started with an engaged community 
member leaving because using Elm had lead him to more failures than successes. 
People ought to ask "is that likely to be the case for me as well" and the 
community ought to ask "how might we fix the things that resulted in those 
failures?" You are right that this code is being made available free by Evan 
(or by NoRedInk since they are funding his work) and as such, it's his call. 
But similarly, it is a call for everyone using Elm as to whether it is still 
working out or whether they would be better off placing their bets elsewhere.

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-css with type classes (a response to the Elm Town podcast)

2017-04-27 Thread Mark Hamburg
Maybe this is covered in OCaml's polymorpic variants — I couldn't tell from
a quick skim — but another feature that would cover this without
introducing type classes is support for more arbitrary union/sum types.
That way, one could write something like:

type Auto = Auto


type alias LengthOrAuto = Int + Auto -- is this a type or a type alias, I'm
not sure

margin : LengthOrAuto -> Style

Handwaving type checking rules would require that a type passed to
something that was expecting a union type needs to cover a subset of that
union type. Case statements would be used to do the discrimination.

The potentially interesting things that come out of something like this are
that one could imagine a union of Maybe and Result which would allow for a
value or an error or nothing. This has got to have been explored somewhere
before. I have no idea what sort of problems it might create for the type
system.

Mark

On Thu, Apr 27, 2017 at 10:53 AM, OvermindDL1  wrote:

> Actually this sounds to exactly like the use-case for OCaml's Polymorphic
> Variants.  In OCaml you could easily use just `Hidden for both of your
> examples, fully type checked, type safe, etc... etc...  Polymorphic
> Variants are just global Variants that are unnamed.  A function can take a
> bounded or unbounded set of them and are perfectly suited for an abstract
> CSS DSL while being readable in both usage and implementation.
>
> And yes, I agree about type classes, they are extremely over-used in
> Haskell where something like OCaml's Implicit Modules would be such a
> significantly better fit for...
>
>
> On Thursday, April 27, 2017 at 6:21:22 AM UTC-6, Mitchell Rosen wrote:
>>
>> Hi Joey,
>>
>> Indeed, basic ADTs are one way to model the DSL. The problem then arises
>> when you want to reuse the name "auto" for another key.
>>
>> I may not have been clear, so I'll try to summarize my post here. How
>> might elm-css look if there were different features in Elm? As it stands,
>> the library seems to be fighting hard against the language, and the result
>> far from beginner-friendly.
>>
>> Type classes are one such extension, and I sketched out how one might
>> implement this library using them. As you mentioned, ADTs are another.
>>
>> In this particular case, type classes, as flawed as they are, seem vastly
>> superior to the row-types approach. But, I'm definitely open to having my
>> mind changed! I'm just not comfortable enough with row types as a language
>> feature to really have an intuitive understanding of when to use them, and
>> when to not.
>>
>> But, anyways, I totally agree that keeping it simple with ADTs is what
>> you should do most of the time. It's only when you're writing library code
>> to be used by the community that you should start obsessing over the
>> ergonomics.
>>
>> --
> 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.
>

-- 
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] Re: Moving on

2017-04-26 Thread Mark Hamburg
The moment Evan gave the "Let's Be Mainstream" talk and linked to it from
elm-lang.org, the pretense that Elm was sheltered in a pre-1.0 world was
pretty heavily undermined. Elm has been promoted as being ready for the
mainstream. The fact that it bears a version number that is less than 1.0
doesn't mean much — at least not without a roadmap spelling out the
differences between where it is now and 1.0.

On Wed, Apr 26, 2017 at 1:00 PM, Joey Eremondi <joey.eremo...@gmail.com>
wrote:

> There is an underlying premise of Elm that there is One Correct Way™ to
>> solve a problem in an application written in Elm, it takes "a long time" to
>> discover the One Correct Way™, and Evan is the only person capable of
>> doing it.
>
>
> It's not that there's one way of doing it, but that once a bad way of
> doing it is widespread, it never dies. Once you give people a tool, you can
> never take it back, even if it is a bad tool. The goal is to make Elm solid
> *before* 1.0, so that after 1.0, we won't be plagued by backwards
> compatibility issues.
>
> On Wed, Apr 26, 2017 at 12:57 PM, Eirik Sletteberg <
> eiriksletteb...@gmail.com> wrote:
>
>> I used the persistent-cache code once. I just copied the source code into
>> my project. The library readme makes some bold statements, like "it is the
>> right technical choice" to expose a LRU cache for localStorage in Elm. It
>> certainly wasn't the right choice for my use case, where "least recently
>> used" wasn't a relevant factor regarding which elements to retain in
>> localStorage; there were a few very important keys, and a couple of "less
>> important" keys. The Task-based LocalStorage API that is included in
>> persistent-cache works very well. It works very well because it mirrors the
>> native API. As a developer, I also prefer the freedom to make my own
>> technical choices that are right given the circumstances. I need the power
>> of the Web API, I just want it with types and without runtime exceptions.
>>
>> There is an underlying premise of Elm that there is One Correct Way™ to
>> solve a problem in an application written in Elm, it takes "a long time" to
>> discover the One Correct Way™, and Evan is the only person capable of
>> doing it. (An exaggeration of course) As far as web APIs are concerned,
>> there is only one Correct Way™ we all have to deal with, which is W3C
>> standards, as they are implemented in the browsers. Maybe it's possible to
>> take WebIDL definitions and convert them to Elm bindings, then one would
>> have a type-safe, exception-free interface to the browsers, without all the
>> maintenance overhead.
>>
>> BDFL for both a language and its ecosystem is perfectly fine for a
>> project philosophy, but it is intrinsically linked to having a small niche
>> community. Then again, broad adoption may not be a significant priority for
>> Elm during the next few years, so that might be a good thing. In the case
>> of commercial software development, cash is king, and delivering working
>> features is the top priority. Nobody cares that your car is shiny and
>> polished, if it cannot drive in reverse. The article Choose Boring
>> Technology <http://mcfunley.com/choose-boring-technology> comes to mind.
>>
>> Bottom line, there is a huge untapped potential here, people are excited
>> about Elm, want to use it in production, but then there are small things
>> like missing support for localStorage, file uploads, audio playback, binary
>> data, being able to control event.preventDefault(). Many of those are
>> problems that people would fix themselves and publish as a package. All it
>> takes is to trust the broader community. Even if you end up with 5
>> different libraries dealing with cookies, one of them will probably
>> prevail, and all 5 of them will learn from each other's advantages and
>> drawbacks. I don't buy the argument that opening up the ecosystem will ruin
>> Elm's guarantees - I would trust the robustness of a third party cookie
>> package with 5000 GitHub stars and 100 merged pull requests just as much as
>> (or more than) I trust the Elm core. Just look at what npm did for the
>> JavaScript community. Look at the success of React and Redux, which are
>> more or less based on TEA. But they have excellent JS interop and an open
>> ecosystem. Wouldn't it be great if Elm were just as widespread? And had
>> just as many contributors?
>>
>>
>> onsdag 26. april 2017 19.28.59 UTC+2 skrev Wojtek Piekutowski følgende:
>>>
>>> The thing is that this exact kind of cache (LRU) might not work for all
&g

Re: [elm-discuss] Re: Moving on

2017-04-26 Thread Mark Hamburg
Exactly and look at the months old comment at the top of the read me:

NOT RELEASED YET — I hope to release it relatively soon, but I cannot make
any promises. Until then, please use ports if you want to use localStorage.


On Wed, Apr 26, 2017 at 9:22 AM Rex van der Spuy 
wrote:

> On Wednesday, April 26, 2017 at 5:07:39 AM UTC-4, Wojtek Piekutowski wrote:
>>
>>
>>  https://github.com/elm-lang/persistent-cache?
>>
>
>  Wow, that's exactly what I need!
>
>
>
>
>
>
>
>
> --
>
>
> 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.
>
>
>

-- 
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] Re: Moving on

2017-04-26 Thread Mark Hamburg
That talk was very interesting and very telling since this was a group
moving from Elm to PureScript not because they wanted more sophisticated
types and more squiggles but rather almost inspite of those aspects and
instead because of ecosystem issues.

Mark

On Wed, Apr 26, 2017 at 2:07 AM Wojciech Piekutowski <
w.piekutow...@gmail.com> wrote:

> Forking is already kind of happening. Not per se, but some people decided
> to stick with 0.16 and FRP. And switched to PureScript for new projects.
> This still fresh talk covers such a case:
> https://www.youtube.com/watch?v=9kGoaUqcq4A
>
> Brief summary of why they didn't use Elm for other projects
> They stayed at 0.16 because of FRP. It isn't cost effective and could not
> be in fact possible to port to 0.17+. They are frustrated with lack of
> communication (not much info beforehand about the tectonic change between
> 0.16 and 0.17 before it happened). There's no roadmap.
>
> I'm wondering if 0.18 TEA couldn't be just a higher level abstraction over
> FRP. That way we would have simplicity for newcomers and smaller apps, but
> also keep the lower level powerful machinery for advanced cases or people
> who don't want/can't to follow TEA.
>
> Similar approach could apply to things like localStorage. Why not have a
> low-level libs more or less mirroring web APIs, but later community could
> build something higher level, like
> https://github.com/elm-lang/persistent-cache?
>
> On 26 April 2017 at 05:19, Mark Hamburg <mhamburg...@gmail.com> wrote:
>
>> This will evolve, but see above, the constraint is that Elm remains
>>> reliable...
>>
>>
>> Which the lack of attention to bug fixes undermines. How long were there
>> warnings that arrays had problems? How long has Elm sometimes generated bad
>> code for cyclic definitions leading to runtime crashes? The speed blog post
>> regarding Elm talks up using Html.Lazy and to do that effectively in some
>> cases you need Html.map. Guess what, use them in the "wrong" way  and you
>> can get type system violations leading to runtime errors.
>>
>> Tight control over the core is something that many language designers
>> have maintained and it leads to clarity. (At the large language end of the
>> spectrum, this has helped C# be a better language than Java despite
>> starting as a Java knock off.) But everything within that tight bound of
>> control then also becomes an area of responsibility or the technical
>> ecosystem suffers.
>>
>> An ecosystem that had looked vibrant and innovative a year ago now looks
>> increasingly buggy and stagnant. We're coming up on the one year
>> anniversary of the Elm 0.17 release in which FRP was removed, effects
>> managers introduced with a plan that they would cover the web APIs, and a
>> new guide to Elm was introduced. The guide long contained promises of
>> material that was coming soon though now it just seems those promises have
>> been deleted rather than fulfilled. The effects manager ecosystem appears
>> to have been abandoned in that nothing new seems to have come to the
>> community in ages. Evan started a manager for local storage but hasn't seen
>> it as worthwhile to finish it leaving people using ports with a range of
>> frustrations (see other threads). Phoenix was cited as an example of where
>> effects managers could be useful but there is no blessed Phoenix effects
>> manager. If you took the velocity of the last nine months and projected it
>> forward, it's hard to make it look promising. People want to help. They
>> want to write and share code to expand what Elm can do, but the evidence
>> suggest that there is a lot of pushback against that right now —
>> particularly when it comes to getting code approved for distribution
>> through the standard package manager.
>>
>> The lack of effects manager build out also reflects a sense that the
>> direction Elm development moves in is capricious. When 0.17 was released,
>> there was a strong message around this being the architecture for the
>> future of Elm and a suggestion that it wasn't going to take that much to
>> get coverage of the standard web API. That appeared to be the plan of
>> record to the extent that there was one. Binary data has been a hot topic
>> for quite a while and the HTTP libraries give nods toward adding support
>> but haven't actually done so. Now, it seems Evan is working on providing
>> ways to download less code or download code incrementally when delivering
>> web apps. That's definitely nice. Smaller is better. But to the extent that
>> there were hints toward a roadmap, this hadn't been on it.
>>
>> T

Re: [elm-discuss] Re: Moving on

2017-04-25 Thread Mark Hamburg
>
> This will evolve, but see above, the constraint is that Elm remains
> reliable...


Which the lack of attention to bug fixes undermines. How long were there
warnings that arrays had problems? How long has Elm sometimes generated bad
code for cyclic definitions leading to runtime crashes? The speed blog post
regarding Elm talks up using Html.Lazy and to do that effectively in some
cases you need Html.map. Guess what, use them in the "wrong" way  and you
can get type system violations leading to runtime errors.

Tight control over the core is something that many language designers have
maintained and it leads to clarity. (At the large language end of the
spectrum, this has helped C# be a better language than Java despite
starting as a Java knock off.) But everything within that tight bound of
control then also becomes an area of responsibility or the technical
ecosystem suffers.

An ecosystem that had looked vibrant and innovative a year ago now looks
increasingly buggy and stagnant. We're coming up on the one year
anniversary of the Elm 0.17 release in which FRP was removed, effects
managers introduced with a plan that they would cover the web APIs, and a
new guide to Elm was introduced. The guide long contained promises of
material that was coming soon though now it just seems those promises have
been deleted rather than fulfilled. The effects manager ecosystem appears
to have been abandoned in that nothing new seems to have come to the
community in ages. Evan started a manager for local storage but hasn't seen
it as worthwhile to finish it leaving people using ports with a range of
frustrations (see other threads). Phoenix was cited as an example of where
effects managers could be useful but there is no blessed Phoenix effects
manager. If you took the velocity of the last nine months and projected it
forward, it's hard to make it look promising. People want to help. They
want to write and share code to expand what Elm can do, but the evidence
suggest that there is a lot of pushback against that right now —
particularly when it comes to getting code approved for distribution
through the standard package manager.

The lack of effects manager build out also reflects a sense that the
direction Elm development moves in is capricious. When 0.17 was released,
there was a strong message around this being the architecture for the
future of Elm and a suggestion that it wasn't going to take that much to
get coverage of the standard web API. That appeared to be the plan of
record to the extent that there was one. Binary data has been a hot topic
for quite a while and the HTTP libraries give nods toward adding support
but haven't actually done so. Now, it seems Evan is working on providing
ways to download less code or download code incrementally when delivering
web apps. That's definitely nice. Smaller is better. But to the extent that
there were hints toward a roadmap, this hadn't been on it.

This is what leads to people being worried or frustrated. This is what
leads to them leaving. There will always be churn. There will always be
people who are unhappy because of the strictures of pure functional
programming or who are unhappy because Elm isn't Haskell. But this thread
started with an active member of the community — as opposed to someone who
just came by to kick the tires — deciding that the ecosystem just wasn't
viable as a place to invest anymore. Maybe this is just a one off. But
maybe it's symptomatic. As web technologies — of which Elm clearly
positions itself as one — demonstrate it doesn't take much  to tilt from
being the hot new thing to being the thing that everyone has heard that
people have gotten burned by and one best stay away.

What you are hearing is frustration and fear. When people talk about forks,
I doubt that it is because they really want to fork Elm. Most of us
recognize that language development is hard. But people are trying to
figure out a backup plan.

As I've said, some people want very specific extensions to the language and
those just don't seem likely to happen. As a language, Elm seems to be
focused on being a strongly-typed, pure functional language that avoids the
complexities of Haskell. That's laudable. (I'm the sort of caveman that
prefers C to C++.) But for the ecosystem, if I look at other successful
languages, it feels like Evan needs to make clear where the boundary lies
for what he wants absolute control over, needs to make a commitment to
making the material inside that boundary as strong as possible, and needs
to figure out how to be supportive of active development outside of that
boundary. Those actions would allow people to make decisions based on facts
rather than hopes and/or fears. It would allow more people to decide up
front whether the Elm ecosystem is where they want to be and if it results
in some people not coming in then it also results in fewer people leaving
noisily or throwing around talk of forks to address issues that don't seem
to be being 

Re: [elm-discuss] Re: Moving on

2017-04-25 Thread Mark Hamburg
I was late to the Lua community — Lua 4.0 verging on 5.0 — but in some ways
at a similar point or earlier to where Elm is trying to be given that at
the time Lua conferences and talks at other conferences were not a common
thing. Lua the language is controlled by three people with the
implementation all being the work of one person. They clearly listen to the
mailing list, but they make decisions themselves about what the language is
going to be and how the implementation is going to work.

But having asserted that control over the core, the Lua team takes bug
fixes very seriously and are aggressive about fixing bugs in releases while
preserving the specification. Elm does not fare as well here with multiple
runtime crash inducing bugs sitting for months at a time.

Furthermore, Lua invested in a strong API for interoperation with native
code and welcomed people writing libraries to extend it. The Lua community
has struggled to have anything like the package repositories of Python or
Perl — it's notorious as a batteries not included language — but there was
express support as opposed to discouragement for rolling up your sleeves
and extending it as you needed. (One result of Lua's friendliness to
extension is that Lua is now at the core of some of the most important
machine learning libraries.) Contrast this with the thin official
documentation around ports and the significant limitations on how those can
be used to access and work with external functionality. It feels like an
"if you must but we'd really rather you didn't" situation.

I don't know how the process on Python worked, but I suspect given the
range of extensions to Python it was similar.

Own and control the core. Be dedicated to making it as high quality as
possible. Make it easy and encouraged for people to provide extensions
beyond the core. Elm certainly practices the first. There are signs of
trouble with respect to the second. Significant issues with regard to the
third are driving people away.

Mark

On Tue, Apr 25, 2017 at 6:27 AM Wojciech Piekutowski <
w.piekutow...@gmail.com> wrote:

> The number of similar voices regarding community process and amount of
> frequently requested missing features/native libraries (like binary support
> and better JS interop) show a problem. No matter how amazing and performant
> Elm will ever be, newcomers will be discouraged by everlasting begging for
> native APIs support.
>
> Does anybody has an idea how other languages/platforms manage to get
> community involved? I think it could be beneficial to learn from, for
> example Elixir community, and borrow some good practices that could work
> for Elm too.
>
> On Tue, 25 Apr 2017 at 05:22, Duane Johnson 
> wrote:
>
>> As several have asked, and Peter Damoc kindly reached out off-list, I'll
>> post here what I wrote to him. Please know that I do appreciate what
>> everyone has worked on, but this hasn't worked for me for the reasons I
>> outline. I've started auto-archiving email from elm-discuss, so if you have
>> any questions, please reach out to me off-list. Thanks.
>>
>> Hi Peter, that's kind of you to follow up off-list.
>>
>> I've had several pain points. I'll go over the technical ones first and
>> the community ones second.
>>
>> In the two (and a half) projects that failed, they failed for different
>> reasons but in general, because of JS interop issues. In the first project,
>> I was unable to access binary data in order to represent compiled hex blobs
>> as visual SVG (see https://github.com/canadaduane/elm-hccb/tree/master).
>> I made a use case post here
>> https://groups.google.com/d/msg/elm-discuss/spr621OlUeo/awhuqzpzBgAJ.
>>
>> In the second case, I was trying to create custom elements that could be
>> embedded inside the QuillJS rich text editor--in other words, it wasn't
>> enough just to treat Javascript as an external API, I needed to embed elm
>> "things" inside a JS component inside elm.
>>
>> I made a third attempt to convert an AngularJS app to Elm, but didn't get
>> very far in and gave up, in part because of the attitude I've felt from the
>> Elm community that components are bad and have no place here (when
>> everything I'm seeing in Angular is trying to be more like a component, and
>> interact with the world like a component).
>>
>> The community aspect that has weighed heavily on me is the feeling that
>> I'm not a participant in the decision-making or priority-setting. I feel
>> more like a distant user, or maybe an interesting use case, from which data
>> is gathered and decisions are made (by someone else, somewhere else).
>>
>> I hope that helps!
>>
>> Thanks again for your reaching out. I really look up to you and eeue56.
>>
>> Take care,
>> Duane
>>
>>
>> On Monday, April 24, 2017 at 4:31:08 PM UTC-6, Joe Andaverde wrote:
>>>
>>> Duane,
>>>
>>> I'm curious what the roadblocks were in the 2 of 3 you didn't have
>>> success with? This could definitely help others when making their decision.

Re: [elm-discuss] Re: Comments on the TEA Components package

2017-04-19 Thread Mark Hamburg
I think we have two general trains of thought regarding development here.

One is YAGNI. Let things grow organically. Refactor when it gets messy.

The other is Build for Success. Over engineer because you will probably end
up shipping the prototype and once you do it will be too late to go back
and do major restructuring.

Each has its place. Each builds for particular outcomes. Each can succeed
or fail in spectacular and unique ways. With great effort, each can emulate
the advantages of the other — ignoring the fact that the advantages are
often in terms of not needing as much effort.

To the extent that we live in a world where we all say "you're free to
develop software however you see fit", we can often take the attitude.
"That's interesting. It wouldn't work for me but I see why you are making
those choices."

Where this turns ugly is when it ceases to be about approaches we
individually find valuable but about how everyone should work.

Let's look at this thread. It was instigated by Marek's "components"
package which got some discussion on elm-dev and which I moved over here to
elm-discuss. The structure camp was essentially looking at this and trying
to judge whether it would help with their own structural work. The YAGNI
camp joined in and said in bold text: "*a Model-View-Update triplet is the
wrong unit of composition for Elm applications."* Not, "I (or we) haven't
found it useful" but "it is wrong". So, now we're off to the races. The
structure camp says (in many more words) "I've seen your alternative and it
isn't a real alternative. It's a pathway that decades of software industry
experience indicates leads to creating big balls of mud." The YAGNI camp
can argue that its statements are strongly worded in the interest of
keeping beginners away from excessive complexity. The structure camp can
argue that it needs to be vocal so that beginners understand the mess that
they may get themselves into on a refactor only as needed path.

Mark

On Wed, Apr 19, 2017 at 2:30 PM, Yosuke Torii  wrote:

> Richard,
>
>
>> Can you think of a way to use this overloaded word in a way where the
>> people in the discussion are not confused by it, even though they think it
>> means different things?
>
>
> I don't know. I just answered the question why I received your message as
> "DIY every time". I'm not looking for the alternative for "component" .
>
> I covered how to grow Elm application code bases
>> ,
>> and Evan covered reuse .
>> What is the remaining problem? :)
>
>
> Again I agree to how to break the monolith and when to do it. But is any
> of those reusable things non-TEA? I find UI libraries at
> packages.elm-lang.com but they are often written in TEA manner. If it is
> not simple, how can they be instead?
>
> Sorry if you have already explained enough. Honestly it is hard to read
> whole of messages, as Noah said.
>
>
> Peter,
>
> The problem is that this approach makes it impossible (as far as I could
>> see) to implement the components that need side effects (like the old
>> RandomGif list)
>
>
> Yeah, I know. But at least, some of the UI widgets that does not have
> side-effects can be solved. As far as I can see, the discussion here is
> not on this stage yet.
>
> I think something like `mapWithCmd : (a -> Cmd msg) -> Html a -> Html msg`
> would solve it. The problem is that it allows any kind of side effects
> including HTTP. But I don't find good explanation of why HTTP via view is
> bad while random (or time stamp too?) is OK.
>
>
> 2017-04-20 5:40 GMT+09:00 Peter Damoc :
>
>>
>>
>> On Wed, Apr 19, 2017 at 11:19 PM, Yosuke Torii 
>> wrote:
>>
>>> I'm curious what makes it sound that way, since as you noted, that is
 not the point I'm making.

>>>
>>> I don't know if others feels like me or not. But at least for me, "no
>>> components" sounds a bit confusing (it is in official guide too).
>>>
>>
>> I view it as destructive so, you're not alone in seeing something not OK
>> with that.
>>
>>
>>> Also, "no components, no nesting TEA" does not answer the problem
>>> discussed here. So how can we do instead? Maybe introducing sortable-table
>>> pattern is more constructive for this discussion. I think it is a variant
>>> of TEA, managing its own state, but still keeping the form of "reusable
>>> *view*". So great!
>>>
>>
>> the sortable table is a clever component that pushed the external call to
>> update inside the view.
>> You still need what used to be the ChildMsg tag but now instead of
>> calling the Child.update and saving the state it receives the updated
>> state and just saves it.
>>
>> Other than the update trick, it's more or less the same thing as the old
>> MUV triplets.
>> You can even use the pattern to do nesting.
>>
>> The problem is that this approach makes it impossible (as far as I 

Re: [elm-discuss] Re: Comments on the TEA Components package

2017-04-19 Thread Mark Hamburg
The monster model design is one aspect that leads to the ball of mud code.
Let's look at the source quote for the term big ball of mud:

A Big Ball of Mud is a haphazardly structured, sprawling, sloppy,
duct-tape-and-baling-wire, spaghetti-code
 jungle. These systems show
unmistakable signs of unregulated growth, and repeated, expedient repair.
Information is shared promiscuously among distant elements of the system,
often to the point where nearly all the important information becomes
global or duplicated. The overall structure of the system may never have
been well defined. If it was, it may have eroded beyond recognition.
Programmers with a shred of architectural sensibility shun these quagmires.
Only those who are unconcerned about architecture, and, perhaps, are
comfortable with the inertia of the day-to-day chore of patching the holes
in these failing dikes, are content to work on such systems.
— Brian Foote and Joseph Yoder, *Big Ball of Mud.* Fourth Conference on
Patterns Languages of Programs (PLoP '97/EuroPLoP '97) Monticello,
Illinois, September 1997

When everything starts out in one place with access to everything else,
it's natural to end up with everything talking to and depending on
everything else — or at least the dependencies are less likely to be well
regulated because there is no mechanism doing the regulation. Now, as
conservative politicians will love to tell you, regulations get in the way
and we can be more productive without them, so yes, this unregulated
environment is seemingly more productive. The type system will help in
detecting out and out errors in making changes but once things get
intertwined, they become less amenable to significant change. That's often
fine for an agile development model in which one focuses on small changes
but I've seen agile teams that could generate lots of small changes but
when faced with needing to do something big found themselves profoundly
stuck. An approach which basically seems to advocate building a monolithic,
intertwined codebase and if that gets to be too much, here are some
techniques to break it down after the fact will work to an extent but will
be fighting to apply order to chaos and almost all the time it will be
easier for a developer trying to get a task done to just add a little more
chaos.

As for your specific advice, it includes several useful points and I've
refactored code using those same techniques, but the distillation of the
don't use nested TEA argument when people have asked what to do instead has
tended to be "use functions" which as I've noted doesn't mean much in a
functional language. (I guess it means use functions rather than types but
since types are what allow us to make illegal states impossible, I don't
think it really comes down to just use functions either.) What TEA and
nested TEA provided was architectural guidance on how to structure things
for long term evolution. Saying, if your update function gets too big you
can handle individual cases with separate functions is I guess useful
advice but something that I would hope would be obvious to most people
working in a functional language. What sort of calling conventions work
well? Which ones don't work well and should be avoided? That's the sort of
architectural advice that can be put into practice early on and expect it
to pay off later when changes need to be made. For example, to buttress the
non-component view of the world, one could push on the fact that many views
do not need to own their own state but can simply be functions that render
state provided from somewhere else. One could phrase that as: "You have a
view function but ask yourself whether you really need a model and an
update or whether those are better handled somewhere else. If you do so,
then you can take a big pile of view code and move it somewhere else and
not need to look at it when trying to figure out what is going on in your
model."

As for C++ example I cited, there is nothing Elm is bringing to the table
that makes it superior to C++ in the case I described. C++ is fully
type-checked. Mutability v immutability was not a concern here. Of concern
was that question "which parts of this are visible to other code for the
benefit of code within the would be library and which parts are visible
because they are expected to be stable interfaces for other code". And the
fact it was a question arose exactly because the code base started as an
entity that only needed to serve itself and for which the refactorings were
all just adjustments within those bounds. The choices were expedient for
immediate development but detrimental to long-term reuse.

Should one build everything to be reusable/replaceable? Almost certainly
not because doing so does come with overhead. But identifying likely break
points where code may need to be either reused or replaced and structure
those break points up front to enable that reduces the effort when you do
need it 

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

2017-04-19 Thread Mark Hamburg
Since the call is for concrete use cases, here is one: Reading from local
storage.

My program wants to cache various things in local storage or for the
purposes of this example it wants to read from various locations in local
storage to get the values needed at various points in the model/UX. If we
didn't use local storage and just used HTTP, we would generate HTTP
requests at the points where we needed the information and using Elm
message routing get the results delivered back. We would like to do the
same thing with local storage as a cache — possibly followed by an HTTP
fallback if we found nothing in local storage but that's beyond the scope
here.

The analogous API to the HTTP case would be something like:

get : (Result Error Json.Decode.Value -> msg) -> String -> Cmd msg


Or to make it more composable — cough, tasks v commands, cough — we might
have:

getTask : String -> Task Error Json.Decode.Value


Given that the Elm local storage effects manager seems to be on indefinite
hold, we need to use ports. So, what does it take to do this using ports?

Command ports don't return results. Subscription ports don't convey
information to the JavaScript side. So, we have to use a pair of them. A
command to trigger work on the JavaScript side and a subscription to
receive values back. But how do we match results coming back with requests
coming in? How do we tag those results appropriately for delivery?

There would seem to be two options:

1. For every request we need to make, create a separate pair of ports. Now,
we don't need to pass in the key string because the key is built into the
port identity. In fact, it would be bad to pass in the key string since
that would reintroduce the question of which response goes with which
request. This approach will work if we can statically enumerate ahead of
time all of the keys we are interested in AND we are prepared to write
JavaScript handler code for each and every request. This might be viable
for the big flat applications that some people like to advocate but it's a
pretty messy maintenance situation and it breaks the moment we can't
statically enumerate the keys of interest.

2. When we send a request in, we tag it with an identifying number and
maintain a dictionary mapping those id's to tagger functions. The
JavaScript side includes the id in its response — basically the same thing
Phoenix push messages do — and the subscription port feeds into logic that
looks up the id and tags and delivers the result. Those of you who are
horrified at the thought of storing functions in the model should perhaps
stop right here because that id to tagger function dictionary is doing
exactly that. But even if one gets beyond that, note that this approach
won't work just like HTTP because we will need at some point before this
becomes a command to update the delivery map. That can either happen by
replacing commands with requests or by allowing arbitrary update code to
touch the shared global id generator and delivery map. Neither approach is
as straightforward as the HTTP case.

This could be addressed by extending command ports to allow them to return
responses but if we're doing that, why not just make them composable and
generate tasks that take a Json.Encode.Value as input and return a Task
PortError Json.Decode.Value (where PortError might just be another
Json.Decode.Value or it might be some other response structure that could
reflect other implementation errors TBD):

port get : Json.Encode.Value -> Task Task.PortError Json.Decode.Value


Now, I can wrap this up in code to do the encoding of strings to JSON
(trivial) and map the resulting task result to do any appropriate decoding
and delivery.

One could argue that this would all be handled in the local storage effect
manager thereby rendering this example moot. But as noted above, that
effects manager seems to be on indefinite hold. Furthermore, local storage
was just a convenient and simple example. The exact same arguments could
apply to almost any storage mechanism we wanted to talk to. If the Elm
community were cranking out effects managers to handle these cases that
would clearly mitigate this issue but that hasn't been happening. What's
more such effects managers would almost certainly end up writing kernel
(née native) code to provide task support for the interaction with
JavaScript so instead of having a single mechanism for marshaling these
interactions and keeping the relevant code out of the kernel, we would
 instead have a growing number of pieces of code wanting kernel rights.

Mark

On Fri, Apr 14, 2017 at 11:39 AM, Simon  wrote:

> +1 for Task ports.
>
> On Friday, 14 April 2017 20:32:24 UTC+2, Nicholas Hollon wrote:
>>
>> The process:
>>
>> 1. Share your ideas, experience, & code on elm-discuss.
>> 2. Accept that you have no direct influence over what Evan works on next.
>> 3. Look at the release history  for Elm.
>> Notice that changes happen slowly. 

Re: [elm-discuss] Re: Comments on the TEA Components package

2017-04-19 Thread Mark Hamburg
Here is where our app is migrating after starting as an intermixture of
view-side code and data-side code.

The high level split is a store and a display. The store knows about things
like how to talk to our server. As I summarized it, the UX code should know
nothing about Phoenix. The display manages the user interaction. Both sides
have state. The store, well, stores information — generally a reflection of
what is on the server or should be on the server. The display, however,
also stores information like whether panels are open, the state of
animations, etc. Just as knowledge of Phoenix doesn't belong in the UX,
knowledge of animations does not belong in the store.

This isn't a radical design by any means. A lot of code is built this way.
It's perhaps more interesting to this discussion to observe that the Elm
community doesn't encourage even this sort of factoring and in fact naive
use of MUV/TEA does lead to a deep intermingling of store and display
concerns. (I guess the "just write one monster model" approach deals with
this by saying that code can choose to only interact with parts of the
model.)

What I've been working through while engineering this split is how to
manage coordination between the two sides.

Sending messages from the display to the store is pretty simple. We've
replaced commands in the update signature with a list of "out messages".
These messages include internal notifications — e.g., canceled, finished,
please shift the target somewhere else, etc — and operations for the world
beyond the display which includes commands to flow out the top of the app,
requests for work by the store, and requests for random number generation
using a shared generator. (This last is much like the effects manager
random logic but it uses the Pcg generator.) The operations are all subject
to command style mapping to adjust the tagging for their responses back to
the display. Notifications are just notifications. The current
implementation involves more boilerplate at every nesting within the
display than I would really like but I'm working on that.

Getting data from the store to the display is more interesting and is an
area I continue to work through.

One naive approach we looked at would be to just hand the store into the
view functions and let them query the store as needed to do their work.
There are two problems with this.

The first is that some display side concepts such as which item is
currently targeted/selected — it's a display-side concept since the server
should never know — need to update in response to store-side changes. For
example, if the selected item goes away, we may want to automatically
select something else. Since we can't do updates during view calls, we need
to provide a way for the display to react to store changes. Our solution
here has been to treat this as one would treat the data if it were entirely
stored on the server: we store a local copy on the display side and perform
a fetch operation to get it from the store. This means that the display
gets to validate its copy and the problem of keeping that copy up to date
is exactly the same as the problem one would have if there were no store
and we were just talking over the wire to a server.(*)

This leads to the second problem: A fetch operation is great for getting
the initial information and replacing commands with operations makes that
pretty easy to implement but how do we keep the data up to date and
relatedly how do we keep track of when the display side loses interest?
Here I'm looking at building a subscription equivalent (an observation?)
but I'm not wild about what it would take to make it efficient in the
presence of say scrolling a grid of several thousand items starting and
stopping observations as the visible items change. But efficiency with
large sets of subscriptions seems like something the Elm implementation
hasn't really worried about either since I think it regenerates and
collects up subscriptions after every mutation — if you adhere to the "no
functions in the model" advice(**), you can't cache your subscriptions
because they hold tagger functions — and has the effects managers diff the
new subscriptions against the old. Maybe things are just efficient enough
as it is but I suspect that it's more likely that with so few effects
managers for Elm, few applications generate large number of subscriptions
at any one time. But lacking any better ideas, we will probably start with
mirroring subscriptions and see whether it blows up the time complexity in
a noticeable way.

Moving on, there's one other bit of code structuring that we've only
recently adopted but which has clarified a lot of code and should help with
writing unit tests. The display side models for the overall experience or
pieces of the experience or particular modal portions of the experience
(e.g, sign in) tend to have a model that hold display specific information
like the state of panels or animations and a logic submodel that holds 

Re: [elm-discuss] Re: Comments on the TEA Components package

2017-04-18 Thread Mark Hamburg
It's certainly reasonable to say that there is a point where pursuing
fractal TEA is overkill and not buying one much but extra plumbing work.
But it is also exactly the case of things like the sign up form where being
able to say "Here is a sign up form. It has a model, messages, update, and
view. You embed it in the rest of your app like this." The goal in a
composable architecture is to have "like this" fit enough of a pattern that
a programmer coming into an embedding situation knows what to expect. TEA
works pretty well for this though it can feel a bit boilerplate heavy. I
would put it as:

It's often easiest to work in a monolithic program and there are things you
can do to mitigate the effects of doing so and thereby build a bigger
monolith. But when a project gets truly large, the ease of building a
monolithic ball of mud gives way to the problems of figuring out what
interacts with what and while the type system will have your back at some
level, there are limits to what it can achieve. But TEA is fractal. You can
build more isolated components using the same architecture and embed them
within your larger program. Do you have multiple pages? It may be natural
to build each of them using the TEA pattern. You can then fit them together
in the parent app as follows... The caveat here is that while this is both
straightforward and robust, it is a noticeable amount of code and
translation at the glue layer, so taking the TEA hammer and smashing pieces
down until you have tiny nuggets is going to leave you with a lot of glue
holding those nuggets together.

Mark

P.S. The checkbox could also have the signature: `checkbox : Bool -> Html
Bool` and one could use `Html.map` to apply the translation into some other
message space. I don't know that that's better.


On Tue, Apr 18, 2017 at 3:36 PM Richard Feldman 
wrote:

> Having read the reddit thread about just starting big and breaking things
>> down, it reminds of arguments I've heard for years about how monolithic
>> programs are easier to work with.
>
>
> This Reddit post
> 
> is about *how to break up a monolith*. It doesn't talk about anything
> else except how to break up a monolith. :)
>
> Abstraction barriers are what make big programs possible. I don't think
>> there is any magic in Elm that changes this fundamental lesson of 60 years
>> of software development.
>
>
> I couldn't agree more! Glad we're on the same page about that.
>
>
>> The rest of the world has looked at TEA and seen value in it and is
>> looking to extend it.
>
>
> If people look at it, see value in it, and then think "okay this works
> great, but how can we take it in a different direction?" - that sounds like
> putting the cart before the horse to me.
>
> I think a lot of people would be happier if they gave the "use the
> simplest API that works" approach a shot. :)
>
>
>> The remark that composing TEA-shaped units isn't what Elm is designed for
>> raises the question of whether we should then be expecting Cmd.map and
>> friends to be going away since that would seem to be exactly what they are
>> designed for.
>>
>
> That's a great question! They are designed to make it easier to work with
> Html and Cmd alongside several message constructors.
>
> Example
>
> Pretend there is no Html.map and I'm writing a reusable view whose entire
> API consists of one function:
>
> checkbox : (Bool -> msg) -> Bool -> Html msg
>
> The only state I care about is whether the checkbox is checked (the Bool
> argument), and the only user interaction is checking or unchecking the box
> (the (Bool -> msg) argument; the caller is free to use whatever Msg type
> they are already working with, no conversion necessary).
>
> Using a higher-order function to manage messages is a great lightweight
> default choice, so I don't miss Html.map at all here. I wouldn't use it
> regardless!
>
> Now let's say what I'm building is not a reusable checkbox, but something
> more complex: a reusable *signup form* that expands in-place when the
> user clicks it.
>
> This will involve a lot more Msg constructors - for recording text entry
> in the username/password fields, HTTP responses for username availability
> checks, expanding and collapsing it, submitting it...overall, a lot more
> going on. Let's say it needs 10 message constructors to work properly.
>
> Using the same API design as we did for checkbox above, we'd write
> something like this:
>
> signupForm : (SignupForm.State -> GiganticRecordOfTenMsgConstructors msg)
> -> SignupForm.State -> Html msg
>
> With this API, reusing this signup form entails spelling out all 10 Msg
> constructors as the first argument to this function. That's a lot more work
> than the single Bool argument needed by checkbox! This is where a more
> heavyweight approach can pay off: creating a new SignupForm.Msg and
> having signupForm return Html 

[elm-discuss] Comments on the TEA Components package

2017-04-18 Thread Mark Hamburg
Marek Fajkus's original announcement was on elm-dev but that list tends to
become disapproving of discussions fast, so I'm moving over to here to
discuss it. The post suggested that it was in the Elm package library but
it seems to have been pulled, so I will point to the Github repository:

https://github.com/turboMaCk/tea-component

I've read the ReadMe but haven't looked at the code or the examples beyond
the ReadMe.

Two things immmediately struck me:

1. It seems like an interesting idea to wrap the embedding up into a single
structure. It doesn't really reduce the boilerplate that much but it makes
it seem simpler because it isn't spread out and the number of type
annotations needed is smaller. I see it as a more elaborate form of lenses
— a structure I've started pushing through my code to consolidate various
idioms (and to reduce copy-paste-change errors when I've got multiple
record fields of the same type and hence the type system won't help me when
I miss a change).

2. This isn't really about defining components — a hot button word with
some people (go read the elm-dev thread) — so much as it is about defining
embeddings of one TEA-shaped unit within another.

Side note on TEA: In Elm 0.16, TEA was all about being composable. The
examples focused on things like going from one counter to multiple
counters. This carried over into Elm 0.17 where Cmd.map and Sub.map were
clearly targeted at this sort of composition and Html.map both helped with
the composition and with making Html.Lazy work in an environment with
composition.(*) But somewhere along the way, portions of the Elm community,
including Evan, seem to have swung hard against composing TEA units and now
just recommend using functions. This ignores the fact that in many cases,
the units can't be encapsulated into single functions. On the other hand,
the accompanying piece with these functions is generally Config arguments
and what this package does is provide a useful standard Config and
functions to work with that Config when embedding.

Turning back to the package in question, I would also question the use of
the term "polymorphic" to describe the more generalized case in that the
thing it describes can't really be used in multiple contexts as presented.
Still, it's good to show that the pattern fits with variations on
TEA-shaped units.

Finally, while it was also interesting to see the material on action
bubbling, I think that using commands to send messages to parents is
probably a dangerous choice since there are few if any guarantees regarding
delivery order. Our solution has been to replace commands with out messages
that subsume commands as one special case. This has given us a lot of
flexibility to handle notifications — e.g., the login component can report
back to the parent on login success, a modal process can report if
canceled, etc — but it does involve more boilerplate. I may see whether I
can adapt Marek's approach to this more general embedding mechanism.

In any event, I recommend that those interested in ways to structure large
Elm programs go look at this. It doesn't radically change anything but it
could be a better way to express the composition of TEA-shaped units.

Mark

(*) Or it would if it weren't for a bug where some nesting of the two leads
to a type system violation and thence generally a runtime error.

-- 
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] Re: Task ports: A proposal to make it easier to integrate JS with Elm.

2017-04-13 Thread Mark Hamburg
Given the existence of Process.sleep, the argument that tasks have to return at 
some point and we couldn't guarantee that from JavaScript seems incredibly weak.

Given that effects manager development seems to have ground to a halt — Local 
storage? Phoenix? — it seems pretty vital for a language that talks up 
integration with JavaScript as one of its top features that there be a 
straightforward way to extend it with JavaScript. Command and subscription 
ports don't qualify because they don't provide a clean way to match requests to 
responses.

Mark

> On Apr 13, 2017, at 12:32 AM, Martin Norbäck Olivers  
> wrote:
> 
> An interesting read!
> However it seems they sort of talk beside a big point of "task ports". My 
> example is not so much communicating with the outside world in a general 
> sense but more communicating with the browser, using in Elm unimplemented 
> browser APIs.
> 
> The responsibility would be completely on the javascript side to return a 
> result, but right now the only way to call these API:s is to write "Native" 
> code, or to make "dual ports", one for sending a command, the result of which 
> is then returned in a subscription and need to be paired with the call 
> without any guarantee of the order of the results etc.
> 
> The question is, why is it worse to have a Task not return a result than to 
> have this other mechanism not deliver a Msg? In both cases you'd get nothing.
> 
> Especially if Native becomes Kernel and even more unapproachable (which in 
> itself is probably a good thing), then we really need a way to have the user 
> make Tasks, or something similar to be able to use the browser APIs.
> 
> For databases, websocket-like stuff, http calls etc, that have internal 
> state, then effect modules are probably better, but for calling a function to 
> get some crypto random or to access LocalStorage? Seems like it's too much to 
> create an effect module for that, just look at the code in my example above. 
> That level of simplicity should really be available if people are going to be 
> able to use browser apis productively.
> 
> Regards,
> Martin
> 
>> Den torsdag 13 april 2017 kl. 07:32:17 UTC+2 skrev John Kelly:
>> Here's​ some context on this request / discussion: 
>> https://www.reddit.com/r/elm/comments/61trtm/hard_things_about_ports_as_task_in_elm/?ref=search_posts
> 
> -- 
> 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.

-- 
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] Cmd.map

2017-03-30 Thread Mark Hamburg
As I said, in your small example it probably doesn't matter. But I've also
seen larger examples with more fields in the top level model. My point is
that if there are any cross-field validity constraints, then it's probably
a bad idea to have lots of code that is not only able to but expected to
produce new models. Classic TEA allows one to have the page handler code
handle pages — keeping the top level model ignorant of the details and
unable to muck with the page model — while the top level code handles and
enforces the constraints for the top level model.

Export as little as possible. If you have constraints on how pieces
interact and you can't just make the type system enforce them, then make
sure there is only one module that can modify those pieces. Reduce the
surface area in case you have to go hunting for bugs.

Mark

On Wed, Mar 29, 2017 at 5:57 PM Witold Szczerba <witoldsz@gmail.com>
wrote:

> I'm not really sure what are you suggesting, Mark. Is it's all really
> about that CSRF token, then OK, I could have hide it behind opaque type and
> expose just the bare minimum, so noone could tinker with it's value. Or I
> could turn the simple architecture into more complicated (extra mappings of
> models and commands?) just in the name of... what would that be? And what
> if all that barriers and safety guards turns against me by being too
> restrictive?
>
> Just because you can change that token, does it mean you could do it by
> mistake? I don't really think that would the case. And if you have to, you
> could just do it, without developing circles around all those "safety"
> guards, I guess...
>
> 30.03.2017 1:36 AM "Mark Hamburg" <mhamburg...@gmail.com> napisał(a):
>
> While it cuts down on the boilerplate, it seems like this creates a fair
> amount of exposure for what might otherwise be internal structures. For
> example, if the page update functions all get and produce full models, then
> each of the modules implementing those update functions becomes a place
> where any cross-field invariants have to be maintained. Now, if you can
> build your model in such a way that all representable states are also
> considered legal — the corollary to making illegal states impossible — then
> you don't have a problem. But if you can't arrange this, then you've taken
> a validity concern and spread it through your codebase. Functional
> programming protects you from a particular data instance being modified but
> you still need to figure out how you guarantee that all data instances that
> get produced are valid. In your little example — which probably is small
> enough not to trigger a problem — would you consider it acceptable for a
> page update to change the CSRF token? If not, then the page update should
> not produce a new Model.
>
> Mark
>
> On Wed, Mar 29, 2017 at 3:29 PM, Witold Szczerba <witoldsz@gmail.com>
> wrote:
>
> The best solution to deal with your problems is to use Swiss knife of
> functional programming, i.e.* function composition*. You would be
> surprised how about anything could be handled by this *simple* technique.
>
> Few weeks ago there was a question asked on Reddit about nesting data in a
> model. It was actually more about structuring the application, so I think
> your questions are related. I have answered providing a little example of
> the structure of my own application. I think you could be interested, so
> please take a look:
>
>
> https://www.reddit.com/r/elm/comments/5wikog/easy_questions_beginners_thread_week_of_20170227/deeptz3/
>
> In my opinion (yes, I am repeating myself) the most simple layout of all
> the "modules" is to have an update functions like this:
>
> *update: XyzMsg -> Model -> ( Model, Cmd Msg )*
>
> Where XyzMsg is the module's message, Model is top level model and Msg is
> top level message. The main update function just delegates to the update
> functions of each module, so it looks like a table of contents of possible
> actions and the main model looks like a table of contents of the possible
> states. It really makes working with the application a pleasure :) Every
> time I go back to the other app written in AngularJS, I feel like I am lost
> in a thick fog.
>
> I hope it helps!
>
> Regards,
> Witold Szczerba
>
> P.S.
> My application has grown a little bit since then, the main model is now a
> little bit different:
>
> type Page
> = NoPage
> | AnnouncementListPage (WebData (List Announcement))
> | AnnouncementItemPage (WebData AnnouncementForm)
> | PayoutCancelledListPage (WebData PayoutListForm)
>
>
> type alias Model =
> { page : Page
> , csrfToken : String
> }
>
> As you can see, now I am able to keep a

Re: [elm-discuss] Cmd.map

2017-03-29 Thread Mark Hamburg
While it cuts down on the boilerplate, it seems like this creates a fair
amount of exposure for what might otherwise be internal structures. For
example, if the page update functions all get and produce full models, then
each of the modules implementing those update functions becomes a place
where any cross-field invariants have to be maintained. Now, if you can
build your model in such a way that all representable states are also
considered legal — the corollary to making illegal states impossible — then
you don't have a problem. But if you can't arrange this, then you've taken
a validity concern and spread it through your codebase. Functional
programming protects you from a particular data instance being modified but
you still need to figure out how you guarantee that all data instances that
get produced are valid. In your little example — which probably is small
enough not to trigger a problem — would you consider it acceptable for a
page update to change the CSRF token? If not, then the page update should
not produce a new Model.

Mark

On Wed, Mar 29, 2017 at 3:29 PM, Witold Szczerba <witoldsz@gmail.com>
wrote:

> The best solution to deal with your problems is to use Swiss knife of
> functional programming, i.e.* function composition*. You would be
> surprised how about anything could be handled by this *simple* technique.
>
> Few weeks ago there was a question asked on Reddit about nesting data in a
> model. It was actually more about structuring the application, so I think
> your questions are related. I have answered providing a little example of
> the structure of my own application. I think you could be interested, so
> please take a look:
>
> https://www.reddit.com/r/elm/comments/5wikog/easy_
> questions_beginners_thread_week_of_20170227/deeptz3/
>
> In my opinion (yes, I am repeating myself) the most simple layout of all
> the "modules" is to have an update functions like this:
>
> *update: XyzMsg -> Model -> ( Model, Cmd Msg )*
>
> Where XyzMsg is the module's message, Model is top level model and Msg is
> top level message. The main update function just delegates to the update
> functions of each module, so it looks like a table of contents of possible
> actions and the main model looks like a table of contents of the possible
> states. It really makes working with the application a pleasure :) Every
> time I go back to the other app written in AngularJS, I feel like I am lost
> in a thick fog.
>
> I hope it helps!
>
> Regards,
> Witold Szczerba
>
> P.S.
> My application has grown a little bit since then, the main model is now a
> little bit different:
>
> type Page
> = NoPage
> | AnnouncementListPage (WebData (List Announcement))
> | AnnouncementItemPage (WebData AnnouncementForm)
> | PayoutCancelledListPage (WebData PayoutListForm)
>
>
> type alias Model =
> { page : Page
> , csrfToken : String
> }
>
> As you can see, now I am able to keep a `csrfToken` independent of the
> current page. Now I can add even more things not related to the actual
> page, like e.g. logged in user.
>
>
> On Wed, Mar 29, 2017 at 11:29 PM, Juan Ibiapina <juanibiap...@gmail.com>
> wrote:
>
>> Thanks for the explanation.
>>
>> I understand the choices made so far, but I still haven't been able to
>> find good solutions for some simple problems:
>>
>> 1. I don't want to have every single possible message handled in the same
>> place. It gets too big.
>>
>> 2. My global update function deals with everything in the app, including
>> a message to update the value of the e-mail input field when the user is
>> typing. This seems like a small concern that should be handled by the login
>> page (or a component?). I don't want to clutter my model with temporary
>> data.
>>
>> 3. On my User info page, my model is the same as other pages, so it has
>> Maybe User. Since I have authorization, I *know* that there will always be
>> a user when I go to the user info page. I want this to be reflected on the
>> code, so I never have to check if there is a user.
>>
>> So far these issues are pointing me towards some sort of page separation,
>> but I haven't been able to come up with something I like yet.
>>
>> On Wed, Mar 29, 2017 at 9:54 PM, Mark Hamburg <mhamburg...@gmail.com>
>> wrote:
>>
>>> The config approach pops up various places — e.g., elm-sortable-table —
>>> but isn't as well specified anywhere that I've seen because it doesn't have
>>> as clear a pattern to specify.
>>>
>>> Cmd.map (and Html,map) come out of what could be called Classic TEA. The
>>> classic Elm architecture was built to a

Re: [elm-discuss] Cmd.map

2017-03-29 Thread Mark Hamburg
The config approach pops up various places — e.g., elm-sortable-table — but
isn't as well specified anywhere that I've seen because it doesn't have as
clear a pattern to specify.

Cmd.map (and Html,map) come out of what could be called Classic TEA. The
classic Elm architecture was built to allow decomposition by using tagged
messages to route through the compound model. For example, if you wanted to
have a number of pages, you could have a top level model that served as a
page switcher and it would use tagged messages to route to the current page
(or to discard messages if they weren't bound for the current page). This
worked well though I know programmers who grouse at the amount of message
routing boilerplate one has to write.

But then people started trying to build React style component models with
this and had trouble. At which point, various people in the Elm community
decided that nesting was a bad idea and advocated strongly for flatness
with functions being the only decomposition mechanism and those without
much in the way of architectural guidance. Basically, this was a case of
the pendulum swinging wildly and the architecture for building complex
applications seemingly getting cast aside without a replacement.

My advice would be to use the message routing patterns from classic TEA in
the places it makes sense to break ones app apart — just know that it isn't
particularly well suited to building components.

For example, our codebase contains a module providing a model and
corresponding messages and update function for managing the sign up/sign in
process. It knows how to talk to our server. It knows what validation to
do. It understands the errors coming back from the server. It knows nothing
about how to display the data and instead provides a function to fill in a
ViewData structure that contains the information needed by the view code.
We can now reuse this logic in a variety of places where we need SUSI
logic. Each of those hosting cases then routes messages to and from the
logic using a message case of the form `ToLogic Logic.Msg` and using
`Cmd.map ToLogic` to promote logic layer messages to view layer messages.

Mark

On Wed, Mar 29, 2017 at 11:50 AM, Juan Ibiapina 
wrote:

> Where can I find more information about that Config approach? I'm not able
> to find a way to organise multiple page applications that I like.
>
> On Wed, Mar 29, 2017 at 6:24 AM, Peter Damoc  wrote:
>
>> If you have a series of pages that each has Cmds and you have these pages
>> unified under one app, you need to lift each page Cmd to become an app Cmd.
>>
>> There used to be a nesting architecture where this was demonstrated but
>> now that's been dropped in favor of the Config approach.
>>
>>
>>
>> On Wed, Mar 29, 2017 at 1:09 AM, Brian Marick 
>> wrote:
>>
>>> I’m having trouble thinking of a scenario in which you’d use `Cmd.map`.
>>>
>>> Is it for a case where you create a `Cmd a` where `a` is something
>>> different than the usual `Msg`, then transform it into a `Msg`? (When would
>>> you do such a thing?)
>>>
>>> Or for a case where you want to change the `Msg` constructor that `Cmd`
>>> “wraps”? (Ditto.)
>>>
>>> --
>>> 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.
>>>
>>
>>
>>
>> --
>> 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+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> --
> Juan
>
> --
> 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.
>

-- 
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] Bug report (Undefined is not a function!)

2017-03-29 Thread Mark Hamburg
I've now seen something like this a few times. The last time I tried to
build an SSCCE, the bug went away when I looked more closely so I expect to
get nasty messages from the bug submission system if I try to report it as
is, but I figured I would see whether anyone else has seen anything like
this in an effort to narrow in.

This Elm code

operationHandlers : List (Operation.Op Msg -> Maybe Updater)
operationHandlers =
[ handleAccountOperation
]

handleAccountOperation : Operation.Op Msg -> Maybe Updater
handleAccountOperation op =
case Debug.log "handleAccountOperation" op of
Operation.Account accountID accountOp ->
applyAccountOperation accountOp
|> Maybe.map (updateAccount accountID)
_ ->
Nothing


produces this JavaScript

var _adobe$adlproj$App_SessionData$operationHandlers = {
ctor: '::',
_0: *_adobe$adlproj$App_SessionData$handleAccountOperation*,
_1: {ctor: '[]'}
};
var _adobe$adlproj$App_SessionData$handleAccountOperation = function (op) {
var _p5 = A2(_elm_lang$core$Debug$log, 'handleAccountOperation', op);
if (_p5.ctor === 'Account') {
return A2(
_elm_lang$core$Maybe$map,
_adobe$adlproj$App_SessionData$updateAccount(_p5._0),
_adobe$adlproj$App_SessionData$applyAccountOperation(_p5._1));
} else {
return _elm_lang$core$Maybe$Nothing;
}
};


Note the problem in bold: At the point where we construct the list, we have
not initialized the variable being stored in the list. When we then try to
call the function at the head of the list, we get informed that it isn't a
function. Boom.

Reversing order does not fix this (and should not be required to fix this).

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] Re: To wrap or not to wrap

2017-03-27 Thread Mark Hamburg
A lot of the code I've written that has dealt with wrapped models has used
the `as` keyword but I've found that it makes the code harder to follow
because the pieces working with the unwrapped model are mixed with the
pieces working with the wrapped model. If I were refactoring the code and
not just getting rid of wrapping, I would probably just unwrap and rewrap
at the API layer and allow the rest of the code to ignore the issue as much
as possible.

Mark

On Mon, Mar 27, 2017 at 5:49 AM, 'Rupert Smith' via Elm Discuss <
elm-discuss@googlegroups.com> wrote:

> On Sunday, March 26, 2017 at 10:57:46 PM UTC+1, Mark Hamburg wrote:
>>
>> I think I have some code that follows this pattern:
>>
>> module Mod exposing (Model, Msg, update)
>>
>> type Model = Model Imp
>>
>> type alias Imp = { ... private stuff goes here ... }
>>
>> update : Msg -> Model -> ( Model, Cmd Msg )
>> update msg (Model imp) =
>> updateImp msg imp |> rewrap
>>
>> rewrap : (Imp, x) -> (Model, x)
>> rewrap (imp, x) =
>>  (Model imp, x)
>>
>>
>>
>>- A concern that this inhibits potential efficiency around cases
>>where the update doesn't change the model but just results in additional
>>commands
>>
>> Bear in mind that you don't have to unwrap/rewrap the model in this case.
> The 'as' keyword lets you pattern match and keep the original at the same
> time:
>
> update msg (Model imp as model) =
>  case msg of
>ThisOneUpdatesImp -> updateImp msg imp |> rewrap
>  | ThisOneDoesnt -> (model, someCmd)
>
> --
> 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.
>

-- 
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] Re: 'Native' -> 'Kernel': a msgpack example

2017-03-27 Thread Mark Hamburg
Specifically to support MessagePack it seems like Elm needs:

1. Support for binary data — even if just as a blob that it can pass around
but not inspect. There are references to blobs in places like the Http
module but this appears to have been consigned to the backburner.

2. Support for binary places in the places you actually need it — e.g., web
sockets and Http.

3. Task based interfaces for web sockets if that's where it is being used —
or a sense that using WebSocket.LowLevel is as blessed as using WebSocket.
This is needed to support composition.

4. Task ports so that one could wire up existing JavaScript message pack
libraries.

In other words, Elm COULD support MessagePack without lots of binary
manipulation support and a port of MessagePack to Elm — though obviously
that might be preferable if performance didn't suffer — but it hinges on a
bunch of edges that feel awkward or neglected in Elm right now.

Mark

On Mon, Mar 27, 2017 at 4:20 PM, Kasey Speakman 
wrote:

> But compared to other compile-to-js languages, Elm is seemingly the one
>> that puts the most the hurdles ahead of easily using the libraries
>> available in the world's most popular language.
>
>
> You are correct. Elm is harder to interop than most other compile-to-js
> platforms. That's because Elm tries to guarantee that all user code is pure
> (as in pure functions). This makes Elm apps continue to be evolvable and
> refactorable despite adding new features. Using native code throws away
> Elm's guarantees, so it is discouraged. Using ports (the blessed way to
> interop) maintains the guarantees at the border, but it has trade-offs as
> you've noted in the original post.
>
> Unfortunately, interop is a hard problem to solve while keeping Elm's
> benefits intact. WIP.
>
> On Sunday, March 26, 2017 at 2:57:11 PM UTC-5, Simon wrote:
>>
>> Ok, I hope that this is just a naming change, but spent too much time in
>> politics not to fixate on choice of language issues!
>> But compared to other compile-to-js languages, Elm is seemingly the one
>> that puts the most the hurdles ahead of easily using the libraries
>> available in the world's most popular language.
>>
>>
>>
>> On Saturday, 25 March 2017 02:52:20 UTC+1, Kasey Speakman wrote:
>>>
>>> Yeah, I regretted posting that 2nd half. I don't use any native modules
>>> myself except the one to return decoders out of ports. And I was getting by
>>> without it via ports, although somewhat less optimally. Maybe some people
>>> really need native stuff, though. I haven't. (And I'm willing to monkey
>>> patch what I use native for now if need be.)
>>>
>>> On Friday, March 24, 2017 at 1:48:01 PM UTC-5, Kasey Speakman wrote:

 Indeed, the post mentions renaming Native to Elm.Kernel and ending the
 native module whitelist (sortof). Expectation management.

 User native module blocking was not mentioned. In our current
 Javascript ecosystem such a thing would make Elm non-viable.

 Well, except that repo-forking and monkey-patching exist.

 On Friday, March 24, 2017 at 6:42:34 AM UTC-5, Rupert Smith wrote:
>
> On Thursday, March 23, 2017 at 8:15:51 PM UTC, Simon wrote:
>>
>> It's pretty clear that these practices are frowned upon, but the
>> shift to 'kernel' sounds like a plan to squeeze the pragmatic 
>> programmer's
>> options further. I hope that's not the case.
>>
>
> I think all that is happening is that Native is being renamed to
> Kernel to reduce confusion. At the moment when we say 'Elm' and 'native' 
> in
> the same sentence we could mean an Elm Native module used to implement its
> kernel, or native javascript code through ports.
>
> I can't be certain of the details but I think your function would just
> be re-written as:
>
> var _user$project$Kernel_Msgpack = function() { ... }
>
> But you won't be able to publish it officially and will have to use
> elm-github-install.
>
> It makes sense to me anyway, the 'kernel' needs to be carefully
> managed as the language takes shape.
>
> --
> 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.
>

-- 
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] Re: To wrap or not to wrap

2017-03-26 Thread Mark Hamburg
I think I have some code that follows this pattern:

module Mod exposing (Model, Msg, update)

type Model = Model Imp

type alias Imp = { ... private stuff goes here ... }

update : Msg -> Model -> ( Model, Cmd Msg )
update msg (Model imp) =
updateImp msg imp |> rewrap

rewrap : (Imp, x) -> (Model, x)
rewrap (imp, x) =
 (Model imp, x)


etc

The chief barriers to this style have been:


   - A bit of distaste for the name imp
   - More boilerplate
   - A concern that this inhibits potential efficiency around cases where
   the update doesn't change the model but just results in additional commands
   - Needing to train everyone working with the code to think in terms of
   "now we're working at the imp" level. (Typical response: Why does Elm make
   everything so hard? — clearly an over statement but I understand the sense
   of pain.)

This is one of those areas where it feels like the right way and the easy
way are further apart than they should be and in my experience that tends
to lead to trouble in codebases.

Mark


On Fri, Mar 24, 2017 at 3:43 PM, 'Rupert Smith' via Elm Discuss <
elm-discuss@googlegroups.com> wrote:

> On Thursday, March 23, 2017 at 4:21:10 PM UTC, Mark Hamburg wrote:
>>
>> Should one wrap a model implemented as a record in a type to keep the
>> details private?
>
>
> If you wrap your Model to keep it private, you will only need to
> wrap/unwrap the functions that the module exposes. Internal functions can
> work with the model directly:
>
> module MyAwesomeModule exposes (update)
>
> type Model = M ModelRecord
>
> type alias ModelRecord = { ... }
>
> update : Msg -> Model -> Model
>
> someUpdateHelper : ModelRecord -> ModelRecord
>
> So perhaps wrapping might not be as great an inconvenience. Just don't
> expose (..) always name the public functions being exposed.
>
> 
>
> Also, I think if you wrap the model, you may end up with public functions
> just to extract stuff from it:
>
> module MyAwesomeModule exposes (getUsername)
>
> type Model = M ModelRecord
> type alias ModelRecord = { userName : String }
>
> getUsername : Model -> String
>
> Which is analogous to Java where, for reasons no-one is prepared to go
> against, we do:
>
> public class Account {
>   private String userName;
>
>   public String getUserName() { return userName; }
>   public void setUserName(String userName) { this.userName = userName; }
> }
>
> When really we could do:
>
> public class Account {
>   public String userName;
> }
>
> (Sometimes I do this, it really annoys some people :-P)
>
> In common with Java, Elm has a different syntax for extracting the
> username with 'dot' notation and for writing a function/method to do it
> (some languages have the same notation for both, which makes changing how
> it is done transparent to the consumer of the interface).
>
> I think if you have fields that other modules need to read, perhaps don't
> wrap them, just wrap stuff that is really private?
>
> type alias Model =
>   { userName : String
>   , private : Private
>   }
>
> type Private = ...
>
> Nothing wrong with a public field, and I think it is better than forcing
> yourself to write extract functions unnecessarily.
>
> --
> 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.
>

-- 
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] To wrap or not to wrap

2017-03-23 Thread Mark Hamburg
Should one wrap a model implemented as a record in a type to keep the
details private? In other words:

type alias Model = { foo : Foo, baz : Baz }

- or -

type Model = M { foo : Foo, baz : Baz }

The former is much easier to work with because one isn't constantly
unwrapping and rewrapping.

The latter keeps code better encapsulated.

I had this discussion with a fellow programmer and he asked whether
immutability makes the encapsulation irrelevant. I argued no because the
exposure of internals means that client code can adopt dependencies on
internal choices — "Just because I have a field named 'foo' doesn't mean I
want a client to know about it" — and more significantly it allows
arbitrary code to create values purporting to be valid Model values. If one
can achieve "make invalid states impossible", that's obviously great but in
practice we rely on limiting construction to impose further invariants.
(For example, if the structures implementing an AVL tree were exposed, the
type system would ensure that we had a DAG but it could do nothing to
ensure anything about ordering or the height values.)

The balance we were left with was that "we're all programmers of good
character and we will consider other modules Models to be opaque even if
they aren't." (I'd have said "we're all gentlemen" but that's sexist.)
This, of course, works until we hire a programmer whose character isn't
quite as good in this regard.

How do others choose in this regard?

Mark

P.S. What I would like — though it would break a lot of existing code — is
for the fields of a record to only be exposed on export if explicitly
exposed a la exposing constructors for types.

-- 
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] Re: Elm FP vs Elm FRP

2017-03-23 Thread Mark Hamburg
Elm's FRP was always somewhat weak in that it didn't allow for monadic
(i.e., flatMappable) signals the way something like Rx does. There were
mathematical reasons for this — e.g., if you can create a signal that
counts mouse clicks then it should arguably give you the same values no
matter when you create it which effectively means that all signals need to
be created at the beginning of your program — but this restriction cost Elm
one of the best reasons for using something like Rx. So, the FRP patterns
in Elm got distilled down over time  into the fold over messages
architecture at the heart of TEA and then FRP went away.

Or at least that's my impression of what happened.

Mark

On Thu, Mar 23, 2017 at 4:05 AM Robert Walter 
wrote:

> Hi Eveline,
>
> Then why is Elm not a FRP anymore?
>
>
> Good question, and I guess the answer could become academic rather
> quickly. Still, what helped me understand it were some answers by Conal
> Elliot where he addresses "What is FRP?":
> http://stackoverflow.com/questions/5875929/specification-for-a-functional-reactive-programming-language
> or
> http://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming/1030631#1030631
> Funnily enough, Conal Elliot is not a big fan of the term FRP and tries to
> convince people to call it "denotative, continuous-time programming".
> Also, Stepen Blackheath felt compelled to make a statement to Elm dropping
> FRP: http://sodium.nz/t/my-comment-on-elm-dropping-frp/69
>
> Now, my attempt to answer your question: one of the two integral parts of
> FRP is to be "temporal continuous". To achieve this, you need a notion of
> "values of time". Elm used to have Signals that denoted exactly that
> (before 0.17). Other FRP systems distinguish between "Cells" and "Streams",
> which where kind of merged together to Signals in Elm.
> Anyway, without having Signals/Streams, i.e. "values over time", you
> cannot say that Elm has FRP baked in anymore. TEA separates data and logic
> completely. You have a model, and the Elm runtime allows you to operate
> (update) and transform (view) it to a representation that can be rendered
> by a browser.
>
> Hope this helps,
> Robert
>
> On Thursday, March 23, 2017 at 10:26:42 AM UTC+1, Eveline van Hal wrote:
>
> Hi everyone,
>
> I'm doing my graduating internship and working on an Elm application. I
> have been trying to figure out what the difference is between Elm before
> 0.17 and after.
>
> I have only used Elm 0.18, so I have not had the FRP experience, but from
> what I have read - the experience seems very much the same but simpler. Is
> this true? Then why is Elm not a FRP anymore?
>
> Further does Evan say in the Farewell to FRP post that there could be
> argued that Elm was never a FRP, but why?
>
> 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.
>
>
>

-- 
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] Re: How do you handle dependencies between updaters?

2017-03-21 Thread Mark Hamburg
We've done that as well in places. But I was mostly looking for an example
of how to access extra data during an update. Another example from our
codebase is accessing the User record (name, email address, etc) which we
store at the top of the session model. The updater for a more specific
state can send an out message up the stack to get the user record for use
in the update without needing to store a copy of the data in the state or
plumb through passing it down everywhere. That said, it isn't clear how
that plumbing compares to the out message plumbing which is not
insubstantial. But using out messages to retrieve values does avoid having
huge and seemingly haphazard parameter lists.

Mark

On Tue, Mar 21, 2017 at 3:20 PM, 'Rupert Smith' via Elm Discuss <
elm-discuss@googlegroups.com> wrote:

> On Tuesday, March 21, 2017 at 6:27:01 PM UTC, Mark Hamburg wrote:
>>
>> P.P.S. If you want your mind more deeply twisted, here is what we do when
>> we want to store the auth token fairly high up but a piece of code needs it
>> for constructing an HTTP request:
>>
>
> Why not use a secure cookie? Then the browser adds it to the request for
> you. It is also more secure and has the advantage that if the user
> CTRL+clicks a link in your application opening up the same application in
> >1 tab, that the cookies flow across automatically.
>
> --
> 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.
>

-- 
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] Re: How do you handle dependencies between updaters?

2017-03-21 Thread Mark Hamburg
And if we were more deeply nested, the NeedAuthorization could also have
been forwarded via code like this — note also that I fixed the failure to
properly type the case entries in my previous message:

applySubModelOutMsg : SubModelOutMsg -> Model -> ( Model, List OutMsg )
applySubModelOutMsg subModelOutMsg model =
case subModelOutMsg of
SubModelCommand cmd ->
( model, [ Command <| Cmd.map ToSubModel cmd ] )
SubModelNeedAuthorization updateGen ->
( model, [ NeedAuthorization (updateGen >> updateSubModel) ] )


Mark


On Tue, Mar 21, 2017 at 11:26 AM, Mark Hamburg <mhamburg...@gmail.com>
wrote:

> Oliver asked whether our out messages approach had an equivalent of
> Cmd.map. I'll paraphrase some code to show how it works. It's definitely
> more code than the simple Cmd approach but it provides more functionality
> as well. I'm simplifying away a lot of details like the fact that the login
> submodel below would probably be stored as a `Maybe Login.Model` since once
> we've logged in we don't need it any more.
>
> update : Msg -> Model -> ( Model, List OutMsg )
> update msg model =
> case msg of
> ToLogin loginMsg ->
> updateLogin (Login.update loginMsg) model
>
> updateLogin :
> (Login.Model -> ( Login.Model, List Login.OutMsg ))
> -> (Model -> ( Model, List OutMsg ))
> updateLogin loginUpdater model =
> Update.start model.login
> |> Update.andThen loginUpdater
> |> Update.map (asLoginIn model)
> |> Update.applyOutMessages applyLoginOutMsg
>
> asLoginIn : Model -> Login.Model -> Model
> asLoginIn model newLogin =
> { model | login = newLogin }
>
> applyLoginOutMsg : Login.OutMsg -> Model -> ( Model, List OutMsg )
> applyLoginOutMsg loginOutMsg model =
> case loginOutMsg of
> Login.Command cmd ->
> ( model, [ Command <| Cmd.map ToLogin cmd ] )
> Login.DidLogin authorization ->
> didLogin authorization model
>
> didLogin : Authorization -> Model -> ( Model, List OutMsg )
> didLogin authorization model = ...
>
> The Update module provides a collection of functions for dealing with
> types with the shape ( Model, List OutMsg ). Update.map maps the model.
> Update.andThen is a monadic chaining operation. Update.applyOutMessages
> folds the out messages over the model performing a series of updates and
> accumulating a new list of out messages (generally of a different type).
>
> Applying out messages is definitely more involved than mapping commands
> and it gets repetitive to always have to handle standard cases like mapping
> commands, but the flexibility to have the submodel signal something like
> the fact that we successfully logged in is a big win and standardizing on
> doing this via out messages builds a more consistent code rhythm than
> adding lots of one off extra results to update functions.
>
> Mark
>
> P.S. If anyone has a recommendation for a better name for
> Update.applyOutMessages, I'd love to hear it. The current name feels
> excessively verbose.
>
> P.P.S. If you want your mind more deeply twisted, here is what we do when
> we want to store the auth token fairly high up but a piece of code needs it
> for constructing an HTTP request:
>
> type SubModelOutMsg
> = Command (Cmd Msg)
>  | NeedAuthorization (Authorization -> SubModel -> ( SubModel, List
> SubModelOutMsg ))
>
> applySubModelOutMsg : SubModelOutMsg -> Model -> ( Model, List OutMsg )
> applySubModelOutMsg subModelOutMsg model =
> case subModelOutMsg of
> Command cmd ->
> ( model, [ Command <| Cmd.map ToSubModel cmd ] )
> NeedAuthorization updateGen ->
> updateSubModel (updateGen model.authorization) model
>
> updateSubModel :
> (SubModel -> ( SubModel, List SubModelOutMsg ) )
> -> (Model -> ( Model, List OutMsg ))
> updateSubModel subModelUpdater model =
> Update.start model.subModel
> |> Update.andThen subModelUpdater
> |> Update.map (asSubModelIn model)
> |> Update.applyOutMessages applySubModelOutMsg
>
>
>
> On Tue, Mar 21, 2017 at 9:11 AM, 'Rupert Smith' via Elm Discuss <
> elm-discuss@googlegroups.com> wrote:
>
>> On Monday, March 20, 2017 at 11:58:38 AM UTC, Eirik Sletteberg wrote:
>>>
>>> In larger Elm apps, it makes sense to divide Updaters so you can
>>> package-by-feature.
>>> For example, a single page application could have updaters like this:
>>>
>>> - Configuration updater
>>> - Session updater
>>> - User Profile updater
>

Re: [elm-discuss] Re: How do you handle dependencies between updaters?

2017-03-21 Thread Mark Hamburg
Oliver asked whether our out messages approach had an equivalent of Cmd.map.
I'll paraphrase some code to show how it works. It's definitely more code
than the simple Cmd approach but it provides more functionality as well.
I'm simplifying away a lot of details like the fact that the login submodel
below would probably be stored as a `Maybe Login.Model` since once we've
logged in we don't need it any more.

update : Msg -> Model -> ( Model, List OutMsg )
update msg model =
case msg of
ToLogin loginMsg ->
updateLogin (Login.update loginMsg) model

updateLogin :
(Login.Model -> ( Login.Model, List Login.OutMsg ))
-> (Model -> ( Model, List OutMsg ))
updateLogin loginUpdater model =
Update.start model.login
|> Update.andThen loginUpdater
|> Update.map (asLoginIn model)
|> Update.applyOutMessages applyLoginOutMsg

asLoginIn : Model -> Login.Model -> Model
asLoginIn model newLogin =
{ model | login = newLogin }

applyLoginOutMsg : Login.OutMsg -> Model -> ( Model, List OutMsg )
applyLoginOutMsg loginOutMsg model =
case loginOutMsg of
Login.Command cmd ->
( model, [ Command <| Cmd.map ToLogin cmd ] )
Login.DidLogin authorization ->
didLogin authorization model

didLogin : Authorization -> Model -> ( Model, List OutMsg )
didLogin authorization model = ...

The Update module provides a collection of functions for dealing with types
with the shape ( Model, List OutMsg ). Update.map maps the model.
Update.andThen is a monadic chaining operation. Update.applyOutMessages
folds the out messages over the model performing a series of updates and
accumulating a new list of out messages (generally of a different type).

Applying out messages is definitely more involved than mapping commands and
it gets repetitive to always have to handle standard cases like mapping
commands, but the flexibility to have the submodel signal something like
the fact that we successfully logged in is a big win and standardizing on
doing this via out messages builds a more consistent code rhythm than
adding lots of one off extra results to update functions.

Mark

P.S. If anyone has a recommendation for a better name for
Update.applyOutMessages, I'd love to hear it. The current name feels
excessively verbose.

P.P.S. If you want your mind more deeply twisted, here is what we do when
we want to store the auth token fairly high up but a piece of code needs it
for constructing an HTTP request:

type SubModelOutMsg
= Command (Cmd Msg)
 | NeedAuthorization (Authorization -> SubModel -> ( SubModel, List
SubModelOutMsg ))

applySubModelOutMsg : SubModelOutMsg -> Model -> ( Model, List OutMsg )
applySubModelOutMsg subModelOutMsg model =
case subModelOutMsg of
Command cmd ->
( model, [ Command <| Cmd.map ToSubModel cmd ] )
NeedAuthorization updateGen ->
updateSubModel (updateGen model.authorization) model

updateSubModel :
(SubModel -> ( SubModel, List SubModelOutMsg ) )
-> (Model -> ( Model, List OutMsg ))
updateSubModel subModelUpdater model =
Update.start model.subModel
|> Update.andThen subModelUpdater
|> Update.map (asSubModelIn model)
|> Update.applyOutMessages applySubModelOutMsg



On Tue, Mar 21, 2017 at 9:11 AM, 'Rupert Smith' via Elm Discuss <
elm-discuss@googlegroups.com> wrote:

> On Monday, March 20, 2017 at 11:58:38 AM UTC, Eirik Sletteberg wrote:
>>
>> In larger Elm apps, it makes sense to divide Updaters so you can
>> package-by-feature.
>> For example, a single page application could have updaters like this:
>>
>> - Configuration updater
>> - Session updater
>> - User Profile updater
>> - User Settings updater
>> - Content updater
>> - Some other business specific updater
>>
>> The challenge is when there are dependencies between Updaters, for
>> example the User Profile model might need data from the Session model, the
>> Session updater might need to send messages to the User updater (Load user
>> profile when session is updated), or the Content updater may need to check
>> for the Session updater (get session ID to send as parameter to the API
>> when fetching content), or some business-specific updater may need to
>> interact with both the Content updater, the User updater, and the
>> Configuration updater.
>>
>
> I would apply a technique similar to CRC Cards from OO design. Instead of
> Class-Responsibility-Collaboration, make it Module-Responsibility-
> Collaborations.
>
> You have got a fair idea of what the split of responsibilities into
> modules is (configuration, session, user profile, user setting, content,
> and so on). For each module it is worth also explicitly spelling out what
> its dependencies (Collaborations) are. Analyzed that way, you might find a
> more optimal grouping of the responsibilities into modules that gives you
> less of a dependency head-ache. Even though that grouping may no longer
> align with your first 

Re: [elm-discuss] Re: How do you handle dependencies between updaters?

2017-03-21 Thread Mark Hamburg
The main reason to separate is when the smaller pieces have their own
conceptual integrity. That becomes something one can manage independently
and maintain more local invariants about thereby making that piece of the
code easier to reason about. But a dependency has to be managed somewhere
and generally that needs to happen wherever things come together in the
model hierarchy.

For example, let's say we have a list of chats and a current chat. We're
going to receive the list of chats from the server. The current chat is
going to be something we're going to determine locally. The protocol that
we speak with the server might be involved enough that we want to wrap this
in its own module. (For example, the server might be shipping deltas rather
than whole lists.) One of the things that can happen is that a chat could
get deleted, so an update to the chat list could cause us to have to update
the current chat. Here is how that code roughly works out. (I've got some
monadic types that make it easier to write update functions, but I'm
staying away from them in this example.)

type alias Model =
{ chatList : ChatList.Model
, currentChat : Maybe ChatID
}

type Msg
= ToChatList ChatList.Msg
| ...

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ToChatList chatListMsg ->
updateChatList (ChatList.update chatListMsg) model

updateChatList : (ChatList.Model -> ( ChatList.Model, Cmd ChatList.Msg ) )
-> Model -> ( Model, Cmd Msg )
updateChatList chatListUpdater model =
let
( newChatList, chatListCmd ) =
chatListUdpater model.chatList
newModel =
{ model | chatList = newChatList }
cmd =
Cmd.map ToChatList chatListCmd
( finalModel, finalCmd ) =
updateChatListDependencies newModel
in
( finalModel, Cmd.batch [ cmd, finalCmd ] )

updateChatListDependencies : Model -> ( Model, Cmd Msg )
updateChatListDependencies model =
let
newCurrentChat =
model.currentChat
|> Maybe.andThen (constrainToChatList (ChatList.getList
model.chatList))
in
( { model | currentChat = newCurrentChat }, Cmd.none )

constrainToChatList : List Chat -> ChatID -> Maybe ChatID
constrainToChatList chatList chatID =
if List.any (Chat.id >> (==) chatID) chatList then
Just chatID
else
Nothing

The key logic here with respect to the dependent values is in updateChatList
and its call to updateChatListDependencies. In this implementation, the
model is not responsible for directly maintaining the list of chats but it
is responsible for maintaining the constraints that depend on the list of
chats.

Mark

On Tue, Mar 21, 2017 at 6:35 AM, Eirik Sletteberg  wrote:

> That was what I was thinking, put all the application state in one model,
> and all updaters will deal with that single model, instead of each Updater
> having its own sub-model. In the end, almost all the data is dependent
> somehow.
>
> tirsdag 21. mars 2017 12.22.15 UTC+1 skrev Fedor Nezhivoi følgende:
>>
>> > for example the User Profile model might need data from the Session
>> model
>>
>> This is probably the biggest issue with how people used to do it in
>> Redux. If you read it closely then you'll see that your data is dependent.
>> By separating it between modules you do not make it in decoupled, you just
>> create more boilerplate and complexity in how it works together. This was
>> one of the reasons Redux discarded `waitFor` mechanism from Flux. If you
>> have dependent data just put it in one reducer, that's it. I guess this
>> pretty much applies here for Elm as well.
>>
> --
> 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.
>

-- 
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] Re: Task ports: A proposal to make it easier to integrate JS with Elm.

2017-03-20 Thread Mark Hamburg
Agreed.

Tasks actually were the core way to do things in 0.16 — though ports then
were more focused on reactive programming models as I recall. Effects (what
essentially became commands) were largely a shim on top of tasks. But then
along came Elm 0.17 and it's emphasis on effects managers accessed via
commands and subscriptions and we started to see less functionality
delivered via tasks. But it feels like effects managers have stalled out —
e.g., Evan's local storage effects manager, documentation, etc — leaving
few clear answers here.

Ports are interesting but as noted don't really scale well for any cases
where you need to send in messages and get back matched responses —
particularly if those responses need to result in different messages to the
app.

So, is there a reason for why Elm doesn't place more emphasis on tasks and
provide something like task ports as a way to leverage JavaScript
functionality?

Mark

On Thu, Mar 9, 2017 at 6:47 PM, Jeff Schomay  wrote:

> Just want to add my desires for this functionality and bump this topic.
>
> My current need is to add a new `li` item to a `ul`, find its offsetTop
> and scroll to it (so that the top of the new item is at the top of the
> window).  I can't find a more "Elm-y" way of doing this besides hitting a
> port to get the offsetTop and then use Dom.Scroll.toY to get there (maybe
> with some animation).  It would be great to chain all of that in a series
> of tasks, but currently I have to make a new message for the port and
> respond to that with my scroll code :-/.
>
> In general, after using Elm a lot over the many months, I'm learning that
> the monadic properties of Tasks (ie. chaining with `andThen`) are extremely
> powerful and expressive and composable, not to mention easier to test with
> libraries like arborist.  I'm just sad that there aren't more api's that
> return Tasks.
>
>
>
> On Saturday, August 13, 2016 at 9:31:07 AM UTC-6, 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 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
>> 

Re: [elm-discuss] Re: Post Examples of Painful Record Updates Here!

2017-03-18 Thread Mark Hamburg
I just had a senior engineer on my team ask me whether it was really the case 
that putting a qualified name or a field access into the beginning of a record 
update would fail to compile. His examples were much like the other examples 
from this thread, but I'm noting this here to make clear that this seems to be 
a routine stumbling block.

Mark

> On Mar 9, 2017, at 3:09 PM, Mark Hamburg <mhamburg...@gmail.com> wrote:
> 
> I got asked for non obfuscated/simplified examples, so let me run through 
> some more realistic code. I would pull from our own codebase but we've often 
> contorted ourselves away from these patterns because they are so ugly so I 
> can't just grab existing code.
> 
> Imagine having a style element that includes information about padding on 
> each side:
> 
> type Rect = { left : Int, top : Int, right : Int, bottom : Int }
> 
> type Style = { padding : Rect, ... }
> 
> Expressing it this way allows us to work with the padding as a whole when 
> useful and to avoid having to work with field names like leftPadding, 
> topPadding, etc (presumably along with leftMargin, topMargin, etc) 
> 
> But now say one wants to change just the left padding. The code has to build 
> a new padding object and then stick it back into the style. A little ugly 
> from the standpoint of repetition, but maybe just...
> 
> { style | padding = { style.padding | left = 10 } }
> 
> Nope. We can't use an expression for the record to be updated. So, instead we 
> have to write something more like:
> 
> let
> oldPadding =
> style.padding
> newPadding =
> { oldPadding | left = 10 }
> in
> { style | padding = newPadding }
> 
> Or we can use the successive wrapping pattern if we have the necessary 
> utility functions:
> 
> 10 |> asLeftIn style.padding |> asPaddingIn style
> 
> And the inability to use an expression to derive the record also means that 
> we can't do something like:
> 
> { Style.default | color = "red" }
> 
> But rather have to write:
> 
> defaultStyle : Style.Style
> defaultStyle = Style.default
> 
> ...
> 
> { defaultStyle | color = "red" }
> 
> I don't have a good answer to the ugliness of the nested update though the 
> successive wrapping pattern would probably be pretty reasonable if we had 
> .field= in addition to .field. But the latter problem seems like the sort of 
> thing that should be very straightforward to solve and would also allow for 
> writing the first version of updating the left padding that I wrote above.
> 
> Mark
> 
>> On Fri, Mar 3, 2017 at 8:44 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:
>> Our codebase suffers from this as well. And unlike what one of the follow 
>> ups noted, this isn't an issue of wanting to add fields. Rather, it's an 
>> issue of not being able to use an expression in the first part of the record 
>> update. In this case, one doesn't even need a general expression but just an 
>> imported value. On the  their hand, members of my team have gotten bit by 
>> and complained about not being able to construct a nested update using what 
>> they thought were the language constructs:
>> 
>> newFoo = { oldFoo | nested = { oldFoo.nested | field = 3 } }
>> 
>> The "best" syntax I've seen for that is something like:
>> 
>> newFoo =
>>  3 |> asFieldIn oldFoo.nested |> asNestedIn oldFoo
>> 
>> But that's pretty obscure as well.
>> 
>> That said, I just added a utility module to our project that is filled with 
>> generic setFoo and asFooIn functions for every field name that seems at all 
>> likely to be used more than once. I would love to have support for .field= 
>> functions to parallel the .field functions. I would have them take the 
>> assigned value as a first parameter and the record as a second parameter to 
>> enable writing:
>> 
>> Slides.defaultConfig
>> |> .someAttribute= myCustomValue
>> 
>> The case where the parameters are reversed which helps with nesting could be 
>> handled using a utility function:
>> 
>>  3
>> |> into oldFoo.nested .field=
>> |> into oldFoo .nested=
>> 
>> Mark
>> 
>>> On Mar 2, 2017, at 10:16 PM, Richard Feldman <richard.t.feld...@gmail.com> 
>>> wrote:
>>> 
>>> Re-posting the first example from Franscisco's thread:
>>> 
>>> There is a common pattern where a library (ex, elm-markdown) will provide a 
>>> default config, to be extended by the user.
>>> 
>>> Here the two ways to do this right now, 

Re: [elm-discuss] Re: Is it possible to create a circular reference in Elm?

2017-03-18 Thread Mark Hamburg
I've been thinking about this as well because functional languages should 
provide a great basis for exploiting multi core systems. You can run the 
evaluation of a "top level" function like `update` in a bump arena allocator — 
and can even re-run the function safely if the arena turns out to be too small 
— and then copy the results out to RC space. This helps with passing data to 
parallel evaluators. It provides rapid collection for large external resources 
like images. All really nice.

But Elm can produce circular references in the form of mutually recursive 
functions. In fact, a self-recursive function has a circular reference albeit a 
special case one that could probably avoid a reference count addition. An 
ability to recognize function free data structures — useful for safe equality 
checks as well — could help but consider that effects manager states are not 
function free nor are Html node structures. So, now you have to partition the 
persistent world into GC data and RC data. There might still be benefits in 
terms of handing off RC data between processors but the introduction of GC 
eliminates the possibility of rapid collection.

What I haven't dug into us whether the mutual references in functions can be 
managed by having all of the functions belong to a let context object that they 
know about and which gets special handling in the reference count design. If 
that could be made to work, we'd be back into a reference counting friendly 
space.

Mark

> On Mar 17, 2017, at 3:26 PM, 'Rupert Smith' via Elm Discuss 
>  wrote:
> 
>> On Thursday, March 16, 2017 at 5:06:59 PM UTC, Rupert Smith wrote:
>> I am guessing the answer is no.
>> 
>> type alias Reader { borrowing : List Book }
>> type alias Book { reader : Maybe Reader }
> 
> My observation about this is that with statically typed languages, the 
> underlying programming language is usually prevented from doing things by the 
> type system to make it more safe. 
> 
> In this case, the type system will happily accept something, but it is the 
> operational specification of the programming language that restricts what the 
> type system allows.
> -- 
> 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.

-- 
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] input value solution

2017-03-14 Thread Mark Hamburg
Is this a correct summary: Updating Html.Attributes.value is bad if the user 
types rapidly because it can fall behind user input and setting the value 
competes with typing but we want to set it when the value in the model changes 
for other reasons?

A couple of "solutions" come to mind:

One is to track where the model value came from and only set the attribute if 
the value didn't come from the input. This makes the model a bit of a pain to 
work with particularly with respect to setting the values but it would seem to 
fix the problem.

An almost solution would be to only set the attribute when the element does not 
have focus. This is only an almost solution because it will block programmatic 
updates when the element is focused. On the other hand, how do you know that 
the programmatic update isn't about to collide with the user typing? Another 
heuristic to throw in would be to start a timer on each input and only set the 
attribute if the element is not focused or sufficient time has elapsed since 
the last input event.

Mark

> On Mar 13, 2017, at 11:28 PM, Yosuke Torii  wrote:
> 
> There have been many discussions about this, but please allow me to pick it 
> up again.
> 
> As far as I know, the problem is briefly summarized as follows:
> 
> `Html.Attributes.value` behaves crazily when we type rapidly. 
> `Html.Attributes.defaultValue` solves this but it does not allow to 
> programmatically change the value. There seems no solution for satisfying 
> both of these requirements.
> 
> I believe this is very common requirement of web/gui apps. How do people 
> address this? Personally, I've been blocked on this for 6 months... So I 
> don't want a clean solution. Any workaround / hack is welcome.
> 
> 
> -- 
> 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.

-- 
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] Re: elm + reactive programming

2017-03-10 Thread Mark Hamburg
Let's consider throttling.

We'll assume that we want to throttle messages of a particular type to not 
arrive more often than a particular interval. The exact rules are exactly the 
sort of thing we want to hide inside the throttle module.

We've got some state to manage. The last time we let a message through, maybe a 
message that hasn't gotten through yet, etc. So, we'll have to put this in a 
value and stash it somewhere in our model.

This state can get updated in two ways. It can receive messages to be throttled 
and it can receive responses to commands that it issues — e.g. requests for 
signals after a particular delay, requests for the current time, etc. Each of 
these forms of update need to return a new state, possibly a command, and 
possibly a message to deliver. A little messy but doable.

The hosting module needs to store the throttle in its model and route 
appropriate messages through the throttle object. Furthermore, when messages 
come back out of the throttle, it needs to route them to a version of the 
update function that doesn't throttle them. This could be handled by having a 
ToThrottle wrapper around the actual messages to be delivered and pulling this 
wrapper off before feeding to the throttle. Again, a little messy but doable.

If we put this all just at an outermost level and put the "real" model inside 
of that, it might make for a reasonable way to segregate the "little bit messy" 
code. On the other hand, if we have parts of the model coming and going — e.g., 
because we have a dynamic list of external items we are observing — and those 
individual parts need to throttle messages for those parts, then we likely end 
up with throttling code and constructs threaded through our model logic and 
structures.

What it feels like one wants to write but can't is the function:

throttle : Float -> Sub msg -> Sub msg

On the other hand, the moment you have merges, streams become potentially 
non-deterministic, so I can see the arguments against them. Is there a yet 
better way to separate concerns — in this case model logic from update 
frequency?

Mark

> On Mar 10, 2017, at 9:13 AM, Martin Norbäck Olivers  wrote:
> 
> The point is not that I want to implement things "on my own" in Elm. The 
> point is that we need to understand the problems before discussing solutions. 
> Elm has high level tools, they're called functions, so any collection of Elm 
> state manipulation and subscriptions etc that you need can be put in 
> functions that the user of your library calls.
> 
> How would you do debouncing/throttling/buffering? Well, you'd have a piece in 
> your state that handles this and call functions from the corresponding module 
> to handle the events. The question is, do we need anything else than tasks 
> and subscriptions to be able to implement this? If not, then we can look at 
> what problems people have and write a good library for it. If we do, then 
> let's explore what that other thing could be.
> 
> It's not just Signals from Elm 0.16, they don't give anything that you don't 
> have in Elm currently. RxJs hav higher order functions on 
> streams/observables, which has never been in Elm.
> 
> If it's more than the inconvenience of explicitly declaring your state, then 
> this is a difference more in the mindset about being able to clearly reason 
> about your state and how it changes in one single place.
> 
>> Den fredag 10 mars 2017 kl. 17:00:41 UTC+1 skrev Răzvan Cosmin Rădulescu:
>> Here's an example of drag implemented in RxJS: 
>> https://github.com/Reactive-Extensions/RxJS/blob/master/examples/dragndrop/dragndrop.js.
>>  Look how simple it is. And there are a bunch of examples in that examples 
>> folder. I think you have the wrong mindset, it is not about "what problems 
>> it solves", you can very well solve the same problem in Elm as you did, but 
>> again, this is more about the difference between C & assembler or Python & C 
>> etc. Why do you choose Python and not assembler? Because it gives you high 
>> level tools to work faster and simpler.
>> 
>> As Andrew mentioned, it's about the plumbing in the end. Reactive 
>> observables just makes working with time simpler, you don't have to keep 
>> track of anything. Sure you can do double click/tap by keeping track of time 
>> in current Elm and do some maths, what happens when you want to detect 3-4-n 
>> clicks? Same with swipe for example, etc. RxJS (and here I'm talking about 
>> RxJS because this is what I experimented with before Elm but could be any 
>> other library) just makes this low level state tracking work for UI 
>> especially really really simple. How would you do 
>> debouncing/trottling/buffering etc. in Elm? I've only seen a module on 
>> debouncing and I have absolutely no idea how it works (I checked the source 
>> code) but it looks super complicated. So if you want to implement some of 
>> this things on your own in Elm currently working with present state and no 
>> 

Re: [elm-discuss] Re: elm + reactive programming

2017-03-10 Thread Mark Hamburg
The real test here for Elm isn't just "can you write a program that throttles 
input". Of course you can. It's can you write a library that would allow people 
who needed to throttle input or detect double-clicks or detect other more 
complicated gestures without needing to know the specifics of how you do such 
things. As others have noted, we could write everything in assembler but we 
don't because that level of detail isn't productive and opens up opportunities 
for mistakes in implementation.

How do you handle timeouts? What if you want to try multiple things and take 
the first response canceling the other work? Reactive and promise systems 
provide standard ways of representing this (though a lot of promise system 
implementations are very weak when it comes to cancelation). And again, if we 
can do it at all in Elm, can we do it in a way that doesn't surface all of the 
details?

When I first started exploring reactive programming seven or eight years ago, 
my go to example was trying to step through a list of image ID's fetching the 
actual image data from an asynchronous service. You want to cancel fetches when 
no longer interested. It's better to keep showing the same stale images than to 
switch to a new stale image. You want to show a spinner if the currently 
displayed image has been out of step with the position in the list for too 
long. And possibly the images themselves aren't a single result but rather a 
stream of images of improving resolution. This is all very succinct in a 
reactive framework.

That said, I've also seen what happens when you then thread reactive concepts 
through a large program particularly with a team that hasn't made the mental 
leap to thinking in terms of signals and particularly if you have backdoors to 
do things like look at the values of signals. The results are a tangled mess. 
So, my assessment is that if you can readily describe a computation with 
signals, that can be a great boon to simplifying code but there are things that 
can't or shouldn't be described with signals. Furthermore, lacking any sort of 
flat map for signals made Elm's previous FRP implementation pretty severely 
limited so I'm not sure it's really a loss. The bigger question is whether Elm 
has alternative means to deliver the sorts of useful abstraction that signal 
libraries provide.

Mark

> On Mar 10, 2017, at 8:53 AM, 'Rupert Smith' via Elm Discuss 
>  wrote:
> 
>> On Thursday, March 9, 2017 at 9:43:41 PM UTC, Răzvan Cosmin Rădulescu wrote:
>> Take for example debounce with 500ms interval, every 500ms it should trigger 
>> the update function with the latest object from the stream, that's it.
> 
> Would be interesting to implement this in Elm and see how it turns out. 
> -- 
> 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.

-- 
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] Re: Post Examples of Painful Record Updates Here!

2017-03-09 Thread Mark Hamburg
I got asked for non obfuscated/simplified examples, so let me run through
some more realistic code. I would pull from our own codebase but we've
often contorted ourselves away from these patterns because they are so ugly
so I can't just grab existing code.

Imagine having a style element that includes information about padding on
each side:

type Rect = { left : Int, top : Int, right : Int, bottom : Int }

type Style = { padding : Rect, ... }


Expressing it this way allows us to work with the padding as a whole when
useful and to avoid having to work with field names like leftPadding,
topPadding, etc (presumably along with leftMargin, topMargin, etc)

But now say one wants to change just the left padding. The code has to
build a new padding object and then stick it back into the style. A little
ugly from the standpoint of repetition, but maybe just...

{ style | padding = { style.padding | left = 10 } }


Nope. We can't use an expression for the record to be updated. So, instead
we have to write something more like:

let
oldPadding =
style.padding
newPadding =
{ oldPadding | left = 10 }
in
{ style | padding = newPadding }


Or we can use the successive wrapping pattern if we have the necessary
utility functions:

10 |> asLeftIn style.padding |> asPaddingIn style


And the inability to use an expression to derive the record also means that
we can't do something like:

{ Style.default | color = "red" }

But rather have to write:


defaultStyle : Style.Style
defaultStyle = Style.default

...

{ defaultStyle | color = "red" }

I don't have a good answer to the ugliness of the nested update though the
successive wrapping pattern would probably be pretty reasonable if we had
.field= in addition to .field. But the latter problem seems like the sort
of thing that should be very straightforward to solve and would also allow
for writing the first version of updating the left padding that I wrote
above.

Mark

On Fri, Mar 3, 2017 at 8:44 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:

> Our codebase suffers from this as well. And unlike what one of the follow
> ups noted, this isn't an issue of wanting to add fields. Rather, it's an
> issue of not being able to use an expression in the first part of the
> record update. In this case, one doesn't even need a general expression but
> just an imported value. On the  their hand, members of my team have gotten
> bit by and complained about not being able to construct a nested update
> using what they thought were the language constructs:
>
> newFoo = { oldFoo | nested = { oldFoo.nested | field = 3 } }
>
> The "best" syntax I've seen for that is something like:
>
> newFoo =
>  3 |> asFieldIn oldFoo.nested |> asNestedIn oldFoo
>
> But that's pretty obscure as well.
>
> That said, I just added a utility module to our project that is filled
> with generic setFoo and asFooIn functions for every field name that seems
> at all likely to be used more than once. I would love to have support for
> .field= functions to parallel the .field functions. I would have them take
> the assigned value as a first parameter and the record as a second
> parameter to enable writing:
>
> Slides.defaultConfig
> |> .someAttribute= myCustomValue
>
> The case where the parameters are reversed which helps with nesting could
> be handled using a utility function:
>
>  3
> |> into oldFoo.nested .field=
> |> into oldFoo .nested=
>
> Mark
>
> On Mar 2, 2017, at 10:16 PM, Richard Feldman <richard.t.feld...@gmail.com>
> wrote:
>
> Re-posting the first example from Franscisco's thread
> <https://groups.google.com/forum/#!topic/elm-discuss/vzcrRdgY1-w>:
>
> There is a common pattern where a library (ex, elm-markdown) will provide
> a default config, to be extended by the user.
>
> Here the two ways to do this right now, one painfully verbose and the
> other relying on exposing values that would read better if fully qualified
> instead of exposed:
>
> import Slides
>
> slidesDefaultConfig =
>   Slides.defaultConfig
>
> myCustomSlidesConfig =
>  { slidesDefaultConfig | someAttribute = myCustomvalue }
>
> or
>
> import Slides exposing (slidesDefaultConfig)
>
> myCustomSlidesConfig =
>  { slidesDefaultConfig | someAttribute = myCustomvalue }
>
> Not a big deal TBH, but annoying.
>
>
> --
> 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.
>
>

-- 
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] Re: Post Examples of Painful Record Updates Here!

2017-03-03 Thread Mark Hamburg
Our codebase suffers from this as well. And unlike what one of the follow ups 
noted, this isn't an issue of wanting to add fields. Rather, it's an issue of 
not being able to use an expression in the first part of the record update. In 
this case, one doesn't even need a general expression but just an imported 
value. On the  their hand, members of my team have gotten bit by and complained 
about not being able to construct a nested update using what they thought were 
the language constructs:

newFoo = { oldFoo | nested = { oldFoo.nested | field = 3 } }

The "best" syntax I've seen for that is something like:

newFoo =
 3 |> asFieldIn oldFoo.nested |> asNestedIn oldFoo

But that's pretty obscure as well.

That said, I just added a utility module to our project that is filled with 
generic setFoo and asFooIn functions for every field name that seems at all 
likely to be used more than once. I would love to have support for .field= 
functions to parallel the .field functions. I would have them take the assigned 
value as a first parameter and the record as a second parameter to enable 
writing:

Slides.defaultConfig
|> .someAttribute= myCustomValue

The case where the parameters are reversed which helps with nesting could be 
handled using a utility function:

 3
|> into oldFoo.nested .field=
|> into oldFoo .nested=

Mark

> On Mar 2, 2017, at 10:16 PM, Richard Feldman  
> wrote:
> 
> Re-posting the first example from Franscisco's thread:
> 
> There is a common pattern where a library (ex, elm-markdown) will provide a 
> default config, to be extended by the user.
> 
> Here the two ways to do this right now, one painfully verbose and the other 
> relying on exposing values that would read better if fully qualified instead 
> of exposed:
> 
> import Slides
> 
> slidesDefaultConfig =
>   Slides.defaultConfig
> 
> myCustomSlidesConfig =
>  { slidesDefaultConfig | someAttribute = myCustomvalue }
> 
> or
> 
> import Slides exposing (slidesDefaultConfig)
> 
> myCustomSlidesConfig =
>  { slidesDefaultConfig | someAttribute = myCustomvalue }
> 
> Not a big deal TBH, but annoying.
> 
> 
> -- 
> 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.

-- 
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] Re: Possible performance bug when using SVG xlink:href?

2017-02-11 Thread Mark Hamburg
How are you passing your model to the rendering function in Html.Lazy without 
it triggering on other changes to the model? Does Html.Lazy not look for 
changes in the function itself and you just use a closure to pass the actual 
model value? That would seem like a bug in Html.Lazy if it did so though you 
would be making it a useful bug.

More technically, as with any other function, the results of Html.Lazy 
functions can (or at least should) only depend on their inputs. Lazy nodes in 
the rendering graph reuse the previous rendering if their inputs haven't 
changed (based on a shallow comparison) and otherwise re-render. You need to 
pass the model to the lazy node in order to have something to render and if the 
model is experiencing shallow changes — e.g., because a non-change may still 
rebuild parts of the model — that should result in re-rendering.

Mark

P.S. I do wonder whether it would be useful to have a deep lazy equivalent that 
would perform a deeper comparison to see whether it could avoid re-rendering. 
As with the existing lazy implementation, it wouldn't need to be "perfect" — 
for example functions might only be subject to shallow comparisons — but 
looking more deeply into the inputs would allow for more rendering patterns in 
which a collection of parameters are collected into a record that might get 
rebuilt on every rendering pass.

> On Feb 8, 2017, at 8:01 AM, 'Rupert Smith' via Elm Discuss 
>  wrote:
> 
>> On Wednesday, February 8, 2017 at 12:43:26 PM UTC, Julian wrote:
>> Any idea if this is expected behavior? Or is this a bug with the virtual dom 
>> code?
> 
> Have you tried Html.Lazy? It performs an extra check on the model to see if 
> it has changed (by reference comparison):
> 
> http://package.elm-lang.org/packages/elm-lang/html/2.0.0/Html-Lazy 
> -- 
> 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.

-- 
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] Re: Html.Attributes.none

2017-01-24 Thread Mark Hamburg
Agreed. I wanted this just the other day as well. For similar reasons, it would 
also be nice to have an “official” Html.none rather than just using Html.text 
“”.

Mark

On Jan 24, 2017, 3:51 PM -0800, OvermindDL1 , wrote:
> Yes, for precisely the same usage.  It is much easier to swap between 
> something and `none` then it it to do list building with if conditions.  I 
> made my own by using a dummy attribute name that should 'never be used' 
> (*cough*) of "nonenonenone".
>
> A side effect is the vdom checking is a little more efficient if more than 1 
> set of things change at once since the overall 'shape' of the vdom does not 
> change.  ^.^
>
>
> On Tuesday, January 24, 2017 at 3:21:31 PM UTC-7, Robert Lee wrote:
> > Would anyone else find --Html.Attributes.none-- useful?
> >
> > none : Html.Attribute a
> >
> > Use cases look like the following.
> >
> > 
> >
> > view: Model -> Html.Html Msg
> >       let
> >             onClickButton =
> >                   case model.isClickedAlready of
> >                         True ->
> >                               Html.Events.onClick Submit
> >
> >                          False ->
> >                                Html.Attributes.none
> >       in
> >             Div [onClickButton] 
> >
> > .
> --
> 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.

-- 
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] Intended usage of -- comments (and elm-format)

2017-01-06 Thread Mark Hamburg
What is the intended usage of -- comments in Elm? I'm used to using them as 
line end comments in other languages and/or lightweight comment lines all to 
themselves but elm-format tends to respond to them by more radically adjusting 
the code layout which suggests either that their intended usage in Elm is 
different than I am expecting or that elm-format needs some work in this regard.

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] Re: Emphasizing /r/elm more

2017-01-04 Thread Mark Hamburg
So, this is really about "please go look at /r/elm too"?

Mark

> On Jan 4, 2017, at 11:08 AM, br...@brianthicks.com wrote:
> 
> Killing elm-discuss is outside the scope of the discussion. The point is to 
> emphasize an underused watering hole, not kill an existing one that works 
> well for a subset of the community.
> 
>> On Jan 4, 2017, at 2:00 PM, Martin DeMello <martindeme...@gmail.com> wrote:
>> 
>> I would argue very strongly against killing elm-discuss. I'm a heavy reddit 
>> user, and I think it simply lacks the features necessary to support 
>> mailing-list-style discussions:
>> 
>> 1. if you subscribe to a lot of subreddits, there is no guarantee you'll be 
>> shown new posts from /r/elm in your front page. gmail lets me see a list of 
>> folders in my sidebar with unread-thread counts for each, so I never have to 
>> think about specifically opening up elm-discuss to check if something new 
>> has been posted
>> 
>> 2. there is no good way to see the messages you have and haven't already 
>> read within a thread. (there are browser plugins that try to help with this 
>> but don't do a particularly good job; it's a hard problem to solve from the 
>> outside)
>> 
>> 3. you get a notification if someone replies to you, but not if someone 
>> replies to that reply.
>> 
>> 4. searching through old conversation is really hard
>> 
>> martin
>> 
>>> On Wed, Jan 4, 2017 at 10:13 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:
>>> I agree that this only works if elm-discuss gets killed. It might, however, 
>>> be necessary to also kill elm-dev because the leakage of elm-discuss 
>>> traffic over into elm-dev will likely become much worse if elm-discuss goes 
>>> away.
>>> 
>>> Mark
>>> 
>>>> On Jan 4, 2017, at 9:34 AM, Rex van der Spuy <dandylio...@gmail.com> wrote:
>>>> 
>>>> 
>>>> 
>>>>> On Wednesday, January 4, 2017 at 12:05:33 PM UTC-5, Brian Hicks wrote:
>>>>> the fact remains that /r/elm is going to be a place that people go to ask 
>>>>> questions, and if nobody is there to answer them we're giving people a 
>>>>> really bad experience.
>>>>> 
>>>> 
>>>> That was my problem: When I started learning Elm I first posted questions 
>>>> on /r/elm. 
>>>> But, I soon found I received many more, and better, replies here on 
>>>> elm-discuss, so I hardly visit /r/elm anymore.
>>>> 
>>>> I think for this move to work need to somehow pull the plug on elm-discuss.
>>>> Maybe we should set a kill date, and then after that just lock down this 
>>>> list for good with a big sign saying "Please visit /r/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.
>>> 
>>> -- 
>>> 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.
>> 
>> -- 
>> 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/rg3fzdyG_VU/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to 
>> elm-discuss+unsubscr...@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.

-- 
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] Re: Emphasizing /r/elm more

2017-01-04 Thread Mark Hamburg
At least going through the mental exercise of "would you move elm-dev to 
reddit" is a way to avoid the frequently fallacious mental trap of "I wouldn't 
do this, but others should". In fact, for any move to any other system, it 
might actually be a good thing for elm-dev to lead the way. That way, the 
argument could be made "we're using it for Elm development discussions and it's 
working great".

Mark

> On Jan 4, 2017, at 10:13 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:
> 
> I agree that this only works if elm-discuss gets killed. It might, however, 
> be necessary to also kill elm-dev because the leakage of elm-discuss traffic 
> over into elm-dev will likely become much worse if elm-discuss goes away.
> 
> Mark
> 
>> On Jan 4, 2017, at 9:34 AM, Rex van der Spuy <dandylio...@gmail.com> wrote:
>> 
>> 
>> 
>>> On Wednesday, January 4, 2017 at 12:05:33 PM UTC-5, Brian Hicks wrote:
>>> the fact remains that /r/elm is going to be a place that people go to ask 
>>> questions, and if nobody is there to answer them we're giving people a 
>>> really bad experience.
>>> 
>> 
>> That was my problem: When I started learning Elm I first posted questions on 
>> /r/elm. 
>> But, I soon found I received many more, and better, replies here on 
>> elm-discuss, so I hardly visit /r/elm anymore.
>> 
>> I think for this move to work need to somehow pull the plug on elm-discuss.
>> Maybe we should set a kill date, and then after that just lock down this 
>> list for good with a big sign saying "Please visit /r/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.

-- 
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] Re: UI effects (align/tether, scroll into view) after elements are inserted

2017-01-04 Thread Mark Hamburg
Part of my issue here is that the documentation for the Dom module makes no 
promises about execution order and hence should presumably be viewed as free to 
change in the future. That said, when I go look at the source, I see that it 
ties execution to requestAnimationFrame which seems good but then leaves me 
still uncertain about when it executes relative to the actual view rendering.

Mark

> On Jan 4, 2017, at 10:15 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:
> 
> I don't have a port. I'm just using the standard Dom package. But it would 
> presumably have similar issues with attempts to interact with elements that 
> aren't there yet.
> 
> Mark
> 
>> On Jan 4, 2017, at 9:30 AM, Sebastian Seilund <seb...@gmail.com> wrote:
>> 
>> Hi Mark. Try to send a message on your port as a command in your `init` 
>> function. In the port JS handler you run `requestAnimationFrame` and find 
>> and focus your element there. Does that work?
>> 
>>> On Wednesday, January 4, 2017 at 8:24:40 AM UTC-8, Mark Hamburg wrote:
>>> We just had a similar concern come up but with the existing Dom package. If 
>>> the init for a model wants to generate a focus command — the autofocus 
>>> property is proving unreliable for reasons as yet undetermined — how can we 
>>> arrange to have that command execute after the view has actually been 
>>> instantiated? Do we need to chain off of animation ticks and wait a round 
>>> or two before the focus task runs?
>>> 
>>> Mark
>>> 
>>>> On Jan 3, 2017, at 10:54 PM, Richard Feldman <richard@gmail.com> wrote:
>>>> 
>>>> Hi Sebastian,
>>>> 
>>>> Elm batches DOM updat`es using requestAnimationFrame, so you should be 
>>>> able to delay until after the next DOM update by wrapping your entire 
>>>> callback (starting from let el = document.body.querySelector(selector)) in 
>>>> a call to requestAnimationFrame.
>>>> 
>>>> See if that works!
>>>> -- 
>>>> 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.

-- 
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] Re: UI effects (align/tether, scroll into view) after elements are inserted

2017-01-04 Thread Mark Hamburg
I don't have a port. I'm just using the standard Dom package. But it would 
presumably have similar issues with attempts to interact with elements that 
aren't there yet.

Mark

> On Jan 4, 2017, at 9:30 AM, Sebastian Seilund <seb...@gmail.com> wrote:
> 
> Hi Mark. Try to send a message on your port as a command in your `init` 
> function. In the port JS handler you run `requestAnimationFrame` and find and 
> focus your element there. Does that work?
> 
>> On Wednesday, January 4, 2017 at 8:24:40 AM UTC-8, Mark Hamburg wrote:
>> We just had a similar concern come up but with the existing Dom package. If 
>> the init for a model wants to generate a focus command — the autofocus 
>> property is proving unreliable for reasons as yet undetermined — how can we 
>> arrange to have that command execute after the view has actually been 
>> instantiated? Do we need to chain off of animation ticks and wait a round or 
>> two before the focus task runs?
>> 
>> Mark
>> 
>>> On Jan 3, 2017, at 10:54 PM, Richard Feldman <richard@gmail.com> wrote:
>>> 
>>> Hi Sebastian,
>>> 
>>> Elm batches DOM updat`es using requestAnimationFrame, so you should be able 
>>> to delay until after the next DOM update by wrapping your entire callback 
>>> (starting from let el = document.body.querySelector(selector)) in a call to 
>>> requestAnimationFrame.
>>> 
>>> See if that works!
>>> -- 
>>> 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.

-- 
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] Re: Emphasizing /r/elm more

2017-01-04 Thread Mark Hamburg
I agree that this only works if elm-discuss gets killed. It might, however, be 
necessary to also kill elm-dev because the leakage of elm-discuss traffic over 
into elm-dev will likely become much worse if elm-discuss goes away.

Mark

> On Jan 4, 2017, at 9:34 AM, Rex van der Spuy  wrote:
> 
> 
> 
>> On Wednesday, January 4, 2017 at 12:05:33 PM UTC-5, Brian Hicks wrote:
>> the fact remains that /r/elm is going to be a place that people go to ask 
>> questions, and if nobody is there to answer them we're giving people a 
>> really bad experience.
>> 
> 
> That was my problem: When I started learning Elm I first posted questions on 
> /r/elm. 
> But, I soon found I received many more, and better, replies here on 
> elm-discuss, so I hardly visit /r/elm anymore.
> 
> I think for this move to work need to somehow pull the plug on elm-discuss.
> Maybe we should set a kill date, and then after that just lock down this list 
> for good with a big sign saying "Please visit /r/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.

-- 
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] Re: Emphasizing /r/elm more

2017-01-04 Thread Mark Hamburg
I'm well aware that the Elm subreddit can and will be moderated. The view point 
I was hearing and relaying was basically a political statement about choosing 
not to support Reddit.

Mark

> On Jan 4, 2017, at 8:38 AM, Charlie Koster  wrote:
> 
> Mark, Reddit is what you make of it. Subreddits (such as /r/elm) are 
> self-moderated and it's easy enough to unsubscribe from the bad ones. I think 
> you can be rest assured that /r/elm will be devoid of hate speech.
> 
> 
> 
> 
> 
> Those are some of my subscriptions and I don't encounter any hate speech at 
> all.
> -- 
> 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.

-- 
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] Re: Emphasizing /r/elm more

2017-01-04 Thread Mark Hamburg
I, in my ungrammatical bubble, should perhaps use some Elm-based software to 
keep me from becoming too casual in my writing. :-P

> On Jan 4, 2017, at 8:32 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:
> 
> Me, in my white male tech bubble, focused on user interface annoyances in 
> Reddit. I asked around with some other developers I work with and have worked 
> with and Reddit (along with Twitter) was viewed as a place that has been too 
> friendly to hate speech — particularly racist and misogynist hate speech — 
> and they were uncomfortable giving Reddit any business.
> 
> Mark
> 
>> On Jan 2, 2017, at 8:23 PM, Mark Hamburg <mhamburg...@gmail.com> wrote:
>> 
>> The web interface to Reddit is abysmal. Email isn't great but Reddit seems 
>> incredibly tedious.
>> 
>>> On Mon, Jan 2, 2017 at 7:21 PM, Charlie Koster <ckoste...@gmail.com> wrote:
>>> I just wanted to confirm one of your assertions anecdotally. In the past 
>>> week I wrote two Elm blog posts and opted to post them to /r/elm rather 
>>> than elm-discuss for precisely the first two bullet points you listed. A 
>>> linear discussion would have been largely unhelpful and distracting.
>>> 
>>> I also wanted to reinforce the importance of good moderation. I've seen 
>>> small subreddits grow and die due to a lack of moderation, but the ones 
>>> that have good moderation that encourage productive discussion end up doing 
>>> well.
>>> -- 
>>> 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.
>> 

-- 
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] Re: Emphasizing /r/elm more

2017-01-04 Thread Mark Hamburg
Me, in my white male tech bubble, focused on user interface annoyances in 
Reddit. I asked around with some other developers I work with and have worked 
with and Reddit (along with Twitter) was viewed as a place that has been too 
friendly to hate speech — particularly racist and misogynist hate speech — and 
they were uncomfortable giving Reddit any business.

Mark

> On Jan 2, 2017, at 8:23 PM, Mark Hamburg <mhamburg...@gmail.com> wrote:
> 
> The web interface to Reddit is abysmal. Email isn't great but Reddit seems 
> incredibly tedious.
> 
>> On Mon, Jan 2, 2017 at 7:21 PM, Charlie Koster <ckoste...@gmail.com> wrote:
>> I just wanted to confirm one of your assertions anecdotally. In the past 
>> week I wrote two Elm blog posts and opted to post them to /r/elm rather than 
>> elm-discuss for precisely the first two bullet points you listed. A linear 
>> discussion would have been largely unhelpful and distracting.
>> 
>> I also wanted to reinforce the importance of good moderation. I've seen 
>> small subreddits grow and die due to a lack of moderation, but the ones that 
>> have good moderation that encourage productive discussion end up doing well.
>> -- 
>> 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.
> 

-- 
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] Re: UI effects (align/tether, scroll into view) after elements are inserted

2017-01-04 Thread Mark Hamburg
We just had a similar concern come up but with the existing Dom package. If the 
init for a model wants to generate a focus command — the autofocus property is 
proving unreliable for reasons as yet undetermined — how can we arrange to have 
that command execute after the view has actually been instantiated? Do we need 
to chain off of animation ticks and wait a round or two before the focus task 
runs?

Mark

> On Jan 3, 2017, at 10:54 PM, Richard Feldman  
> wrote:
> 
> Hi Sebastian,
> 
> Elm batches DOM updat`es using requestAnimationFrame, so you should be able 
> to delay until after the next DOM update by wrapping your entire callback 
> (starting from let el = document.body.querySelector(selector)) in a call to 
> requestAnimationFrame.
> 
> See if that works!
> -- 
> 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.

-- 
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] Re: Emphasizing /r/elm more

2017-01-02 Thread Mark Hamburg
The web interface to Reddit is abysmal. Email isn't great but Reddit seems
incredibly tedious.

On Mon, Jan 2, 2017 at 7:21 PM, Charlie Koster  wrote:

> I just wanted to confirm one of your assertions anecdotally. In the past
> week I wrote two Elm blog posts and opted to post them to /r/elm rather
> than elm-discuss for precisely the first two bullet points you listed. A
> linear discussion would have been largely unhelpful and distracting.
>
> I also wanted to reinforce the importance of good moderation. I've seen
> small subreddits grow and die due to a lack of moderation, but the ones
> that have good moderation that encourage productive discussion end up doing
> well.
>
> --
> 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.
>

-- 
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] Weird bug where messages passed to the wrong 'component'

2016-12-31 Thread Mark Hamburg
Tracked down and reported against the virtual DOM but the short summary for 
anyone else seeing routing problems — though possibly not the ones that started 
this thread — is that DOM updates have trouble if you have a lazy node that 
resolves to an Html.map node. Don't do that. At least until there's a fix. If 
you want to be lazy, stick a div in or avoid the map by pushing the tagger 
function further down.

Mark

> On Dec 14, 2016, at 10:23 PM, Mark Hamburg <mhamburg...@gmail.com> wrote:
> 
> I'm looking at a bug tonight that looks very much like a tagger got dropped 
> in processing messages coming up the HTML tree. This is with various bits of 
> Html.Keyed paranoia. I'm thinking more and more strongly that there are bugs 
> in the tagging logic in the virtual DOM. I guess I know what I'm hunting for 
> over Christmas...
> 
> Mark
> 
>> On Wed, Dec 14, 2016 at 7:17 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:
>> I was dealing with a case where a textfield from a login screen would blur 
>> after the screen had been removed and replaced by the main content. 
>> (Literally. I was looking at the new content.) The blur message would get 
>> tagged as headed for the content area which would then lead to a crash when 
>> the message wasn't understood.
>> 
>> My fix was to put an Html.Keyed at the top of the tree to reflect what state 
>> the app was in. (And then in a bit of paranoia, I looked for other, similar 
>> places further down and added Html.Keyed protection there as well.)
>> 
>> Mark
>> 
>>> On Dec 13, 2016, at 10:24 PM, Simon <hotbe...@gmail.com> wrote:
>>> 
>>> Thanks, I suspected that keyed would be part of the solution.
>>> Any sense on whether I need to apply it only to the components being left 
>>> (easy) with no need on those that the code is switching to (much leasy in 
>>> my case)?
>>> 
>>> 
>>>> On Wednesday, 14 December 2016 03:55:29 UTC+1, Mark Hamburg wrote:
>>>> I just dug into what I think is essentially the same bug. My guess was 
>>>> that textfields were getting removed from the DOM and then firing their 
>>>> blur events up through the event mapping chain — which had been updated to 
>>>> match the new view tree structure. It's on my list to try to build a small 
>>>> example of the bug after my team gets through its next milestone.
>>>> 
>>>> In the meantime, I worked around this by making fairly aggressive use of 
>>>> Html.Keyed to prevent pieces of the DOM from being reused.
>>>> 
>>>> Mark
>>>> 
>>>>> On Dec 13, 2016, at 9:56 AM, Simon <hotb...@gmail.com> wrote:
>>>>> 
>>>>> Sorry about using the C word!
>>>>> 
>>>>> I had an error several months ago (0.16/0.17) where the wrong data would 
>>>>> be attached to message, causing all sorts of weirdness. It happened after 
>>>>> a successful logon and as the App tried to redirect to the main view. I 
>>>>> have a vague feeling that in the end all I needed to do was update 
>>>>> elm-lang/virtual-dom.
>>>>> 
>>>>> Anyway, it has come back. It has something to do with when the browser 
>>>>> puts in login information for you. I can create the error by deleting the 
>>>>> auto-input and inserting my password and clicking enter to submit.
>>>>> 
>>>>> Then what I see in my logs is this message
>>>>> 
>>>>> `User.SwitchGroup: Blur "password"`
>>>>> 
>>>>> Whereas SwitchGroup has type `String -> Msg` and `Blur "password"` are 
>>>>> artefacts of the elm-form library that was used in the Login component 
>>>>> and is not used in the User one.
>>>>> 
>>>>> Does this remind anyone of something they have experienced, solved, and 
>>>>> remembered how they solved it?
>>>>> 
>>>>> -- 
>>>>> 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.
> 

-- 
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] Re: Elm "faster than JavaScript" (version 0.18) - NOT - Parts I and II...

2016-12-28 Thread Mark Hamburg
Thinking about this further, yes, one can wrap the logic to talk to a pair of 
ports in a way that makes them work like commands that actually include 
responses. Doing so, however, requires the following departures from standard 
Elm practice:

1. Communicate up from update functions using lists of out messages rather than 
commands. We need to do this so that we can route the requests to the logic 
handling the ports. (In practice, I find this pattern helpful in other ways as 
well, but it does depart from standard Elm practice and it requires more 
plumbing work for each point where modules get glued together.)

2. Store (tagging) functions in the portion of the model handling the ports so 
that results can be tagged for delivery when they come in through the 
subscription port. This goes against the "don't store functions in the model" 
advice and makes it unsafe to use the equality operator with ones model — 
though I suspect that in practice it would prove to be safe.

This is essentially the process of building and using what I referred to as a 
pseudo-effects manager. If anyone really wants example code, I can try to get 
some written up. If persistent cache doesn't become available soon, I may be 
writing this anyway to handle the logic for talking to local storage.

But even with this "solution" in hand, we're still not in a great position to 
address the issue of moving performance critical code out of Elm and into 
JavaScript. The above design can wrap that logic in something that behaves much 
like a command, but those and this are awkward to thread through a computation. 
In comparison, when I've tried taking synchronous algorithms and breaking out 
pieces into tasks — e.g., to access a database — the refactoring process is 
actually pretty straightforward. So, having some official, documented way to 
create JavaScript-based tasks would still be a huge win in opening up an escape 
hatch for performance issues and access to other functionality.

Mark

> On Dec 28, 2016, at 12:06 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:
> 
> Ports as they exist in 0.18 do not appear to offer this. If you want to make 
> a request and receive a response, you need to make the request through a 
> command port and receive the response through a subscription port. If you 
> want to make multiple requests and receive multiple responses, you must do 
> something to match responses with the code waiting for them which generally 
> means generating and managing some form of ID's. The code to do that starts 
> to look a lot like an effects manager, but the documentation discourages 
> writing those. One could probably make this work via an out message based 
> design with a pseudo-effects manager at the top level to manage ID's and talk 
> to the ports but note that this pseudo-effects manager will be part of the 
> model and will be storing functions — something that there is also advice to 
> avoid doing.

-- 
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] Re: Elm "faster than JavaScript" (version 0.18) - NOT - Parts I and II...

2016-12-28 Thread Mark Hamburg
Just to make it clear, I'm not particularly calling for an easier way to create 
"subscriptions". I'm calling for a way to do one of the following — either is 
fine, each have their pluses and minuses:

1. Expose a synchronous, externally defined function that takes JSON (or really 
anything a command port supports) in and returns JSON (or really anything a 
subscription port supports) out.

- or -

2. Expose a factory for externally defined asynchronous tasks where the task 
when executed receives JSON (etc) in and resolves to JSON (etc) when finished.

The former is easier to integrate into general computation. The latter more 
clearly reflects that the computation occurs "elsewhere" and must be managed as 
such.

Ports as they exist in 0.18 do not appear to offer this. If you want to make a 
request and receive a response, you need to make the request through a command 
port and receive the response through a subscription port. If you want to make 
multiple requests and receive multiple responses, you must do something to 
match responses with the code waiting for them which generally means generating 
and managing some form of ID's. The code to do that starts to look a lot like 
an effects manager, but the documentation discourages writing those. One could 
probably make this work via an out message based design with a pseudo-effects 
manager at the top level to manage ID's and talk to the ports but note that 
this pseudo-effects manager will be part of the model and will be storing 
functions — something that there is also advice to avoid doing.

Or if ports are a sufficient answer and I'm just not seeing it, then maybe we 
need more and better examples for, in the case of this thread, how you move an 
expensive computation out of Elm and over to JavaScript.

Mark

> On Dec 27, 2016, at 11:41 PM, GordonBGood <gordonbg...@gmail.com> wrote:
> 
> 
> 
>> On Wednesday, 28 December 2016 14:18:13 UTC+7, Mark Hamburg wrote:
>> My point was that the calls for Elm optimization could largely be mitigated 
>> through a combination of fast enough for most purposes (arguably already 
>> there) coupled with a reasonable escape hatch to the host environment (as of 
>> now JavaScript and not really there) for the cases when it isn't. I'm 
>> suggesting that rather than investing in fancy compiler changes, some 
>> changes in the runtime architecture to allow performance intensive central 
>> loops to be written in other ways would be cheaper, simpler, and would 
>> arguably address some of the other issues that have floated up recently.
>> 
>> Elm has a weird ambivalence about native code. On the one hand, Evan has 
>> pushed back pretty hard in the past out of fear of getting tied to crappy 
>> JavaScript libraries and has pushed for doing everything in Elm. This is 
>> reflected in the relatively small amount of native code based work in the 
>> standard Elm package repository. On the other hand, when pushed on how one 
>> is supposed to do something that is currently difficult in Elm — e.g., some 
>> MDL conventions — others in the community have pushed for using native code 
>> rather than trying to write it in Elm.
>> 
>> My recommendation would be a middle path that says we believe most things 
>> are better in Elm but here are its limitations and here is how you can 
>> cleanly and easily reach outside of Elm when those limitations prove to be a 
>> problem. While the currently documented mechanisms may be clean, they aren't 
>> easy for many cases. Ports are extremely awkward for cases that require both 
>> a request and a response to that request. Effects managers are undocumented 
>> and discouraged. And native modules themselves are barely even admitted to 
>> let alone documented as a thing. Improve that situation and any concerns 
>> over both performance and interfacing to the broader world are substantially 
>> mitigated and Elm can better focus on its core mission. Fail to improve that 
>> situation and every effort to grow the market for Elm will also grow the 
>> pressure for it to do everything well.
> 
> Mark, you raise a good point:  as an interim measure, make it easier to 
> generally interface to JavaScript including easily adding subscriptions if 
> necessary.  But that will only happen if Evan and others see it that way, 
> which they may not if they see it as "Elm is already good enough (for our 
> use)".
> -- 
> 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.

-- 
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] Re: Elm "faster than JavaScript" (version 0.18) - NOT - Parts I and II...

2016-12-27 Thread Mark Hamburg
My point was that the calls for Elm optimization could largely be mitigated 
through a combination of fast enough for most purposes (arguably already there) 
coupled with a reasonable escape hatch to the host environment (as of now 
JavaScript and not really there) for the cases when it isn't. I'm suggesting 
that rather than investing in fancy compiler changes, some changes in the 
runtime architecture to allow performance intensive central loops to be written 
in other ways would be cheaper, simpler, and would arguably address some of the 
other issues that have floated up recently.

Elm has a weird ambivalence about native code. On the one hand, Evan has pushed 
back pretty hard in the past out of fear of getting tied to crappy JavaScript 
libraries and has pushed for doing everything in Elm. This is reflected in the 
relatively small amount of native code based work in the standard Elm package 
repository. On the other hand, when pushed on how one is supposed to do 
something that is currently difficult in Elm — e.g., some MDL conventions — 
others in the community have pushed for using native code rather than trying to 
write it in Elm.

My recommendation would be a middle path that says we believe most things are 
better in Elm but here are its limitations and here is how you can cleanly and 
easily reach outside of Elm when those limitations prove to be a problem. While 
the currently documented mechanisms may be clean, they aren't easy for many 
cases. Ports are extremely awkward for cases that require both a request and a 
response to that request. Effects managers are undocumented and discouraged. 
And native modules themselves are barely even admitted to let alone documented 
as a thing. Improve that situation and any concerns over both performance and 
interfacing to the broader world are substantially mitigated and Elm can better 
focus on its core mission. Fail to improve that situation and every effort to 
grow the market for Elm will also grow the pressure for it to do everything 
well.

Mark

> On Dec 27, 2016, at 10:49 PM, Peter Damoc  wrote:
> 
>> On Wed, Dec 28, 2016 at 6:40 AM, GordonBGood  wrote:
>> But we stray from the subject of "Elm as fast as JavaScript"...
> 
> In my memory, Evan said that Elm can potentially be faster than JS. This 
> means some future where Elm is wide enough spread and wasm wide enough 
> adopted to have the resources and the context for an efficient compiler that 
> bypasses JS. This is years away so... what are we discussing here? 
> 
> Personally, I believe in the mantra of "Make It Work, Make It Right, Make It 
> Fast". 
> 
> Elm's speed is not a show stopper for the vast majority of Elm developers. 
> Sure, it might prevent some potential users from taking Elm seriously for 
> certain tasks but... what is better? catering for the needs of a very small 
> set of potential users or catering for the needs of the vast majority of 
> actual Elm users? 
> 
>> My point is that I love the practicality of Elm with its simple yet 
>> functional syntax and would like never to be forced to use JavaScript or 
>> even Typescript again, but am forced to do so for certain types of 
>> applications due to these inefficiencies.
> 
> Or you can look at it from the other way: for certain types of applications 
> you can already use a practical, simple language (Elm). :) 
> 
> 
> -- 
> 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+unsubscr...@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.


Re: [elm-discuss] Re: Elm "faster than JavaScript" (version 0.18) - NOT - Parts I and II...

2016-12-27 Thread Mark Hamburg
This could, however, feed into the questions over Elm's interface to 
JavaScript. The easier it is to escape to JavaScript, the easier it is to say 
that Elm is fast enough for the vast majority of code that matters and if that 
doesn't cover a tight loop in your code, you can write just that part in 
JavaScript.

I've spent a long time working in Lua which has a fairly fast implementation as 
scripting languages go, but also had a very straightforward and powerful escape 
hatch to C. The former meant that one could expect to write most logic in Lua 
and not worry about performance. The latter meant that if performance were a 
problem, it would be easy to address when it came up.

The net from this for Elm is that I would argue that compiler optimizations can 
focus on easy wins provided that it is easy to move a computation to JavaScript 
when that doesn't work. At this point, however, that isn't possible because 
launching a computation through a command and waiting for a result back on a 
subscription where that result must be distinguished from all other results 
from other command driven requests is a mess. At the very least, please give us 
task ports so that we can readily fire off asynchronous computations with 
results — though for use as an escape hatch when Elm is too slow, I can feel 
the pressure for a synchronous native code extension mechanism.

Mark

> On Dec 27, 2016, at 5:10 AM, Noah Hall  wrote:
> 
> Tight calculation loops and performance matters a lot in some cases
> such as complex form validation. I've spoken with at least one company
> suffering these bottlenecks with Elm, but it was resolvable by just
> changing how the data is modelled.
> 
> For performance in production, if you're not running a game, then the
> longest computational time is likely from multiple re-renders. Which
> is thankfully not an issue. TBH, we do not care in production if Elm
> is the "fastest". We care if it is "fast enough", which it is.
> 
> On Tue, Dec 27, 2016 at 2:01 PM, Robin Heggelund Hansen
>  wrote:
>> I was the one who raised the original issue. The reason there is only a 20%
>> performance in the given example is because the comparison operator isn't
>> the bottleneck of the code, which tests retrieving an object from an
>> immutable array with 10.000 elements. What you are testing is essentially
>> only measuring the overhead of a comparison operation. Still, my benchmark
>> is able to run at 7,5 million ops per second, running on a macbook air from
>> 2013. This is fast enough for most web apps, and this brings me to my next
>> point.
>> 
>> Elm is, at least currently, a language to make web applications. How often
>> are you going to run calculations in tight loops where the performance
>> impact of comparison or equality operators gives a noticeable performance
>> impact for the end user in a web browser?
>> 
>> I'm not saying that the proposed optimisation isn't worthwhile, it is. But
>> Elm, being a 0.x language still, has a lot more important things to improve
>> on before it turns its attention back to performance, which is already very
>> good. Things like hot-code reloading, improved package manager and bug
>> fixes.
>> 
>> 
>> tirsdag 27. desember 2016 03.41.29 UTC+1 skrev GordonBGood følgende:
>>> 
>>> 
>>> 
 On Tuesday, 27 December 2016 05:37:43 UTC+7, Robin Heggelund Hansen wrote:
 
 Part I: Evan is already aware of this issue, you can see the full
 discussion in this github issue:
 https://github.com/elm-lang/elm-compiler/issues/1528
 The short of it is that the code generator part of the compiler is not
 aware of type information, and adding this would be a serious undertaking.
 It will probably come at some point, as there are interesting optimizations
 that can be made, like the one mentioned
>>> 
>>> 
>>> Although it is good to see that Even is aware of the issue, it is
>>> discouraging to learn that the type information is not retained by the code
>>> generator and therefore this improvement is part of a "huge project"; thus
>>> the linked issue has been closed.  The person who raised the original issue
>>> developed some timing results that showed only about a 20% speed improvement
>>> for the particular code use.  However, when I compare the above tight loop
>>> written directly in JavaScript, the difference here is about 700%!  Of
>>> course, real use cases won't be quite this large, but I could see a fairly
>>> tight loop being 300% (+/- 100%) faster.
>>> 
 
 
 Part II: Bitwise operators are inlined in 0.18, which gave a noticable
 performance boost in libraries like Skinney/elm-array-exploration and
 mgold/random-pcg. Having it available as a function (just like +, -, * 
 etc.)
 allows more flexibility like currying.
>>> 
>>> 
>>> I checked and you are right that these functions are now inlined.
>>> 
>>> The only other thing they should also have is infix for those 

[elm-discuss] Faster subscription logic: A thought

2016-12-22 Thread Mark Hamburg
When I look at applications I've built in the past and the parts of them
that would naturally be represented using subscriptions — e.g.,
subscriptions for image status (or even image data) on a grid of images — I
worry about how well they scale. In particular:

* As I understand it, subscriptions is called after every cycle through
update. This makes it a potential point of significant expense if the work
load is significant. This might not be essential, but if there is a
guarantee that if the current state of a model does not return a
subscription then the model will not receive messages from subscriptions
established by earlier states of the model, then it probably is essential.

* The subscriptions function has to operate on all parts of the model that
can generate subscriptions.

* The effects manager code has to diff the lists of subscriptions provided
to it. This results in a trend toward subscriptions having globally unique
identifiers which can be awkward/expensive if there is any nesting. (See,
for example, Http.Progress.)

So, subscriptions are calculated often, have a cost when calculated
proportional to the model size (in general), and then require a way to
efficiently diff them in the effects managers.

This sounds a lot like what happens with views and we know that Elm has a
very fast view system. (There are blog posts that say so!) So, what if
subscriptions borrowed a bit more from views:

• Sub.batch is essentially the equivalent of creating a parent node.

• Sub.map is essentially the equivalent of Html.map

• We could add Sub.Lazy as a way to avoid recomputing subscriptions

• Sub.Keyed or Sub.keyedBatch could also help with subscriptions coming and
going

• The diff could be computed by the same tree diff logic that would make
Sub.Lazy work and could report new subscriptions and subscriptions that
were going away and possibly "changed" subscriptions if we had an idea of
such a thing.

Put this together and the compute costs for subscriptions become
proportional to the size of changes to the model as opposed to to the model
size and effects managers don't need to do as much book keeping themselves.
This should make it more palatable to update subscriptions frequently.

Turning back to my photos example, this would, for example mean that I
could structure the logic so that computing subscriptions looks at the
portion of the photo grid that is visible and generates a subscription
keyed by photo_id for each visible photo. These subscriptions are generated
as being lazy themselves so that they don't get
regenerated when a photo stays visible and the diff logic gets to exploit
the fact that they aren't changing:

subscriptions { photoArray, firstVisible, lastVisible } =
Sub.lazy3 subscriptions_ photoArray firstVisible lastVisible

subscriptions_ photoArray firstVisible lastVisible =
   Array.slice firstVisible lastVisible photoArray
   |> Array.map (\photo -> ( photo.id, photoSubscriptions photo )
   |> Array.toList
   |> Sub.keyedBatch

photoSubscriptions photo =
Sub.lazy photoSubscriptions_ photo

etc

Mark

P.S. This example also makes me want Array.sliceMapToList but that's a
different matter. To really be efficient on huge numbers of photos, I would
probably want to use something other than an array.

-- 
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] Awaiting effects managers: Persistent cache and Phoenix

2016-12-19 Thread Mark Hamburg
What is the status on the persistent cache effects manager?

https://github.com/elm-lang/persistent-cache

What is the status on the Phoenix effects manager?

https://github.com/saschatimme/elm-phoenix

Thanks.
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] Stance on native APIs for 0.18?

2016-12-16 Thread Mark Hamburg
My view of the ideal world here with respect to JavaScript is that
JavaScript (or any other foreign language host) is basically a separate
universe that gets orchestrated by and communicates with Elm. Since Elm is
implemented as compiling to JavaScript and it runs within the JavaScript
universe, we can't actually protect it from ill-behavior in that universe
but that's an artifact of implementation. If one pretends that the Elm and
JavaScript universes are separate — because some day they might be — then
one needs to recognize that it is very difficult to arrange for synchronous
behavior in another universe. Many systems allow one to do it, but it tends
to block in ugly ways and if at all possible you want to avoid it. So, I
think it's pretty natural to view Elm's interaction with an external
universe as consisting of tasks to perform (asynchronously) and potentially
subscriptions by which to watch that universe — again asynchronously.

One of the challenges in multi-universe systems is object lifetimes.
Cross-universe GC is hard as a general problem. If, however, we say that
the JavaScript universe is subordinate to the Elm universe in that Elm can
hold references to JavaScript objects but not the other way around, then
this problem goes away.

One area where I will admit this notion is less clear is how animation or
anything requiring tight — i.e., synchronous — coupling should work. In
this case, the JavaScript universe essentially wants to fire off a message
to Elm and then block waiting for a return value. That's a pain for the
JavaScript side but it's what is essentially happening now anyway. If
animation synchronization didn't matter, then one could imagine a version
in which the JavaScript universe would fire off strobes at animation frames
to which the Elm universe could respond by calling view and pushing a new
HTML tree back to JavaScript. The JavaScript universe would not, however,
block in the meantime. The net result might be pretty similar to where
things are now but it feels like there could be slightly greater
opportunity for skew.

Mark

On Fri, Dec 16, 2016 at 4:39 AM, Vojtěch Král 
wrote:

>
> Dne čtvrtek 15. prosince 2016 19:44:20 UTC+1 Roland Kuhn napsal(a):
>>
>>
>> Again wrong: just having a certain type does not enable client code to
>> handle the fallout—because the effects of JS code are literally arbitrary.
>> The only achieved effect is that the fallout is signaled in the type
>> system. But then if most of the code is reasonable despite being JS, most
>> people will just run these Tasks as if they’re fine anyway, and the
>> function of the type marker is lost—it just makes life a little more
>> miserable where people are forced to jump through hoops.
>>
>
> That's not entirely true. I agree that generaly the problem of JS code
> having arbitrary side-effects cannot be solved statically/automatically,
> but these type system facilities (Task, Result) do help, methinks. They can
> be useful for handling errors that are expected as well as, for example,
> catching JS exceptions thrown down the stack. I definitely wouldn't mark
> them useless.
>
> Anyhow, did anyone manage to get Evan's opinion on this thread?
>
> --
> 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.
>

-- 
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] Re: Stance on native APIs for 0.18?

2016-12-15 Thread Mark Hamburg
Having external compute run asynchronously opens the possibility of having
it run in parallel some day. That said, if Elm were to emphasize that sort
of programming, it might drive some shifts in how other pieces are
structured. The world is going async — see node.js — but it's a painful
process. Tasks might be enough but I don't know that anyone has written a
complex process around tasks and any such process wouldn't leverage the Elm
debugger. A bigger problem is that once you ask for something to be
computed, it really helps if there is a way to say "nevermind". Reactive
networks also help hide some of the management issues for this sort of work
but Elm has been moving away from those.

So, I embrace async tasks but I think they also then need to be embraced by
the language/runtime/app-architecture.

Mark

On Wed, Dec 14, 2016 at 9:03 PM, Desmond D'Souza 
wrote:

>
>
> On Wednesday, December 14, 2016 at 1:30:48 PM UTC-6, Rupert Smith wrote:
>>
>> On Wednesday, December 14, 2016 at 6:00:14 PM UTC, Desmond D'Souza wrote:
>>>
>>> I would love to be able to make synchronous functional calls to js and
>>> get a Result back.
>>>
>>
>> Would you want to publish this code to elm-package?
>>
>
> Yes.
>
>
>>
>> Would the javascript your package calls be included in the package?
>>
>
> I don't know, but do have a naive answer. If I had written all of it in
> Elm, split into App.elm and GraphLayout.elm, I could publish both modules
> bundled into a single package or split into two, and Elm + elm-package
> spells out what a *package user* needs to know and do in both cases. If
> GraphLayout is in javascript, the overall package story should stay as
> close as reasonably possible *for the package user, *and Elm +
> elm-package should spell out what that user needs to know and do.
>
> --
> 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.
>

-- 
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] Weird bug where messages passed to the wrong 'component'

2016-12-14 Thread Mark Hamburg
I was dealing with a case where a textfield from a login screen would blur 
after the screen had been removed and replaced by the main content. (Literally. 
I was looking at the new content.) The blur message would get tagged as headed 
for the content area which would then lead to a crash when the message wasn't 
understood.

My fix was to put an Html.Keyed at the top of the tree to reflect what state 
the app was in. (And then in a bit of paranoia, I looked for other, similar 
places further down and added Html.Keyed protection there as well.)

Mark

> On Dec 13, 2016, at 10:24 PM, Simon <hotbe...@gmail.com> wrote:
> 
> Thanks, I suspected that keyed would be part of the solution.
> Any sense on whether I need to apply it only to the components being left 
> (easy) with no need on those that the code is switching to (much leasy in my 
> case)?
> 
> 
>> On Wednesday, 14 December 2016 03:55:29 UTC+1, Mark Hamburg wrote:
>> I just dug into what I think is essentially the same bug. My guess was that 
>> textfields were getting removed from the DOM and then firing their blur 
>> events up through the event mapping chain — which had been updated to match 
>> the new view tree structure. It's on my list to try to build a small example 
>> of the bug after my team gets through its next milestone.
>> 
>> In the meantime, I worked around this by making fairly aggressive use of 
>> Html.Keyed to prevent pieces of the DOM from being reused.
>> 
>> Mark
>> 
>>> On Dec 13, 2016, at 9:56 AM, Simon <hotb...@gmail.com> wrote:
>>> 
>>> Sorry about using the C word!
>>> 
>>> I had an error several months ago (0.16/0.17) where the wrong data would be 
>>> attached to message, causing all sorts of weirdness. It happened after a 
>>> successful logon and as the App tried to redirect to the main view. I have 
>>> a vague feeling that in the end all I needed to do was update 
>>> elm-lang/virtual-dom.
>>> 
>>> Anyway, it has come back. It has something to do with when the browser puts 
>>> in login information for you. I can create the error by deleting the 
>>> auto-input and inserting my password and clicking enter to submit.
>>> 
>>> Then what I see in my logs is this message
>>> 
>>> `User.SwitchGroup: Blur "password"`
>>> 
>>> Whereas SwitchGroup has type `String -> Msg` and `Blur "password"` are 
>>> artefacts of the elm-form library that was used in the Login component and 
>>> is not used in the User one.
>>> 
>>> Does this remind anyone of something they have experienced, solved, and 
>>> remembered how they solved it?
>>> 
>>> -- 
>>> 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.

-- 
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] Re: Stance on native APIs for 0.18?

2016-12-13 Thread Mark Hamburg
I basically look on it as code that exists to make Elm run at all. That's
basically what Native exists for. (Native also plays games with the type
system but that's another matter.)

And then there's external code that I would like to run that isn't critical
to Elm being Elm. That seems a natural place to deploy Tasks.

Mark

On Tue, Dec 13, 2016 at 8:06 PM, Mark Hamburg <mhamburg...@gmail.com> wrote:

> Then people would complain that all native calls returned Results rather
> than the type they wanted returned.
>
> Mark
>
> On Tue, Dec 13, 2016 at 7:42 AM, Joey Eremondi <joey.eremo...@gmail.com>
> wrote:
>
>> the elm package repo would very quickly get poluted with js code that
>>> causes runtime exceptions
>>
>>
>> But, Tasks have error handling built into them. We could do something
>> similar with synchronous code, just catch any exceptions thrown, and treat
>> the value in Elm as something like a Result.
>>
>> --
>> 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.
>>
>
>

-- 
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] Re: Stance on native APIs for 0.18?

2016-12-13 Thread Mark Hamburg
Then people would complain that all native calls returned Results rather
than the type they wanted returned.

Mark

On Tue, Dec 13, 2016 at 7:42 AM, Joey Eremondi 
wrote:

> the elm package repo would very quickly get poluted with js code that
>> causes runtime exceptions
>
>
> But, Tasks have error handling built into them. We could do something
> similar with synchronous code, just catch any exceptions thrown, and treat
> the value in Elm as something like a Result.
>
> --
> 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.
>

-- 
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] Weird bug where messages passed to the wrong 'component'

2016-12-13 Thread Mark Hamburg
I just dug into what I think is essentially the same bug. My guess was that 
textfields were getting removed from the DOM and then firing their blur events 
up through the event mapping chain — which had been updated to match the new 
view tree structure. It's on my list to try to build a small example of the bug 
after my team gets through its next milestone.

In the meantime, I worked around this by making fairly aggressive use of 
Html.Keyed to prevent pieces of the DOM from being reused.

Mark

> On Dec 13, 2016, at 9:56 AM, Simon  wrote:
> 
> Sorry about using the C word!
> 
> I had an error several months ago (0.16/0.17) where the wrong data would be 
> attached to message, causing all sorts of weirdness. It happened after a 
> successful logon and as the App tried to redirect to the main view. I have a 
> vague feeling that in the end all I needed to do was update 
> elm-lang/virtual-dom.
> 
> Anyway, it has come back. It has something to do with when the browser puts 
> in login information for you. I can create the error by deleting the 
> auto-input and inserting my password and clicking enter to submit.
> 
> Then what I see in my logs is this message
> 
> `User.SwitchGroup: Blur "password"`
> 
> Whereas SwitchGroup has type `String -> Msg` and `Blur "password"` are 
> artefacts of the elm-form library that was used in the Login component and is 
> not used in the User one.
> 
> Does this remind anyone of something they have experienced, solved, and 
> remembered how they solved it?
> 
> -- 
> 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.

-- 
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] Re: Stance on native APIs for 0.18?

2016-12-12 Thread Mark Hamburg
A better way of putting this: Haskell's IO monad structures a particular
set of interactions with the outside world. By making all foreign
interactions go through tasks, Elm could use its task monad to structure
interactions with the outside world. The difference then is that Haskell
has more syntactic sugar around monads than Elm does.

Mark

On Mon, Dec 12, 2016 at 8:19 PM, Mark Hamburg <mhamburg...@gmail.com> wrote:

> One doesn't need them to be asynchronous but making them asynchronous
> helps reinforce the notion that this is happening outside the Elm universe.
> And if you want monads, Elm's tasks are monadic.
>
> Mark
>
> On Mon, Dec 12, 2016 at 6:16 AM, 'Rupert Smith' via Elm Discuss <
> elm-discuss@googlegroups.com> wrote:
>
>> On Friday, December 9, 2016 at 8:07:33 PM UTC, Mark Hamburg wrote:
>>>
>>> While there are certainly times when synchronous calls would have been
>>> nice, I recognize that having synchronous behavior for potentially mutable
>>> external state also tends to imply a lot about execution order — something
>>> that a pure functional language expects to be more free about. Hence, I
>>> think it's reasonable to force operations that need to deal with the
>>> external world to be asynchronous.
>>>
>>
>> Consider monads in other fp langauges. You don't need to have an
>> asynchronous model to work with external state and side effects.
>>
>> I suppose you could describe Elm's event driven loop as a monad, in the
>> sense that it chains together sequences of functions over messages.
>>
>> --
>> 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.
>>
>
>

-- 
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] Re: Stance on native APIs for 0.18?

2016-12-12 Thread Mark Hamburg
One doesn't need them to be asynchronous but making them asynchronous helps
reinforce the notion that this is happening outside the Elm universe. And
if you want monads, Elm's tasks are monadic.

Mark

On Mon, Dec 12, 2016 at 6:16 AM, 'Rupert Smith' via Elm Discuss <
elm-discuss@googlegroups.com> wrote:

> On Friday, December 9, 2016 at 8:07:33 PM UTC, Mark Hamburg wrote:
>>
>> While there are certainly times when synchronous calls would have been
>> nice, I recognize that having synchronous behavior for potentially mutable
>> external state also tends to imply a lot about execution order — something
>> that a pure functional language expects to be more free about. Hence, I
>> think it's reasonable to force operations that need to deal with the
>> external world to be asynchronous.
>>
>
> Consider monads in other fp langauges. You don't need to have an
> asynchronous model to work with external state and side effects.
>
> I suppose you could describe Elm's event driven loop as a monad, in the
> sense that it chains together sequences of functions over messages.
>
> --
> 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.
>

-- 
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] Re: [elm-dev] Re: 0.17 Tasks vs Cmds

2016-12-12 Thread Mark Hamburg
More "implementation" notes for this theoretical discussion. If you dropped
off earlier, you can stay dropped off and leave it to Janis and me. If you
are following along, here's another little tweak:

I just looked at the implementation of tasks and saw that they make very
heavy use of andThen. They probably don't need to be implemented this way,
but they are. So, I would simplify the logic I present above and and get
rid of the deferred queue. When an animation frame occurs, it enqueues all
of the active tasks for the tick and then runs the execution queue until it
is empty before actually invoking the view function. The moment something
triggers code that does not resolve immediately, it ceases to be an issue
ahead of the view rendering, but until that happens we chew through
everything that is outstanding. This could be a bit more work before doing
the animation rendering, but it's simpler code and simpler to explain.

Mark

On Mon, Dec 12, 2016 at 6:03 AM, Mark Hamburg <mhamburg...@gmail.com> wrote:

> Ah. Sorry. My misunderstanding. I went looking for the Effects.tick
> replacement in 0.17+ and only found AnimationFrame.
>
> Mark
>
> On Sun, Dec 11, 2016 at 10:32 PM Janis Voigtländer <
> janis.voigtlaen...@gmail.com> wrote:
>
>> Mark, wow, a lot of material. I’m not able to digest all of it right now.
>> But something quick I want to say, because I have the impression that there
>> is a misunderstanding about the current state of tick batching support.
>>
>>
>> This:
>>
>>
>>
>>
>> Since I wasn’t proposing to get rid of subscriptions and since this
>> functionality is covered through subscriptions, my proposal arguably
>> doesn’t cause a problem.
>>
>>
>>
>>
>> baffles me. I’m not sure what you mean by “this functionality is covered
>> through subscriptions”. Tick batching wasn’t covered through signals (the
>> closest predecessors of subscriptions), and isn’t covered through
>> subscriptions (or at all!) right now.
>>
>>
>> Specifically and relatedly, concerning this:
>>
>>
>>
>>
>> The special behavior for tick wasn’t particularly documented for the 0.16
>> Effects module and isn’t really documented for the 0.17+ AnimationFrame
>> module.
>>
>>
>>
>>
>> I should clarify that the tick batching trick as existed in the 0.16
>> Effects module is *not implemented* for Elm 0.17+. Apparently since
>> gamey stuff is not anymore in Elm’s focus, Evan didn’t bring the “first
>> ever effect manager” over to the new world when effect managers as such
>> became a thing.
>>
>>
>> (Did I indicate previously that tick batching as existed before is a
>> thing currently in core or other 0.17/0.18 packages? I don’t think so. I
>> was only bringing it up as a thing that can be done with effect managers
>> and benefits from, maybe even is absolutely dependent on, having separate
>> concepts of Task and Cmd. To decide about maintaining that latter
>> stance, will require digesting your material more fully.)
>>
>>
>> ​
>>
>> 2016-12-11 21:26 GMT+01:00 Mark Hamburg <mhamburg...@gmail.com>:
>>
>> Since I wasn't proposing to get rid of subscriptions and since this
>> functionality is covered through subscriptions, my proposal arguably
>> doesn't cause a problem. But that's just getting through the loophole of
>> this specific example to dodge this particular case, so let me see if I can
>> get straight what the special property is that we need to preserve if we
>> were still trying to implement a tick command in the same manner of the
>> 0.16 tick effect. (It's worth noting as a side note that in 0.16, all
>> effects other than tick were tasks, so obviously tasks are close to
>> covering the role of commands — née effects — but tick may point to extra
>> wrinkles.) I'm not going to assume a constraint by the current task
>> implementation, but any revised implementation has to have a clear behavior
>> in conjunction with the existing task APIs since its those APIs that make
>> tasks an attractive alternative to commands.
>>
>> The special behavior for tick wasn't particularly documented for the 0.16
>> Effects module and isn't really documented for the 0.17+ AnimationFrame
>> module. Am I correct that the concern is that when the animation frame
>> "arrives":
>>
>>
>>1. We run all of the update functions before actually calling the
>>view function; and
>>2. Any tick effects that result from those updates will be batched
>>together for the next animation frame
>>
>> Was 

Re: [elm-discuss] Re: [elm-dev] Re: 0.17 Tasks vs Cmds

2016-12-12 Thread Mark Hamburg
Ah. Sorry. My misunderstanding. I went looking for the Effects.tick
replacement in 0.17+ and only found AnimationFrame.

Mark

On Sun, Dec 11, 2016 at 10:32 PM Janis Voigtländer <
janis.voigtlaen...@gmail.com> wrote:

> Mark, wow, a lot of material. I’m not able to digest all of it right now.
> But something quick I want to say, because I have the impression that there
> is a misunderstanding about the current state of tick batching support.
>
>
> This:
>
>
>
>
> Since I wasn’t proposing to get rid of subscriptions and since this
> functionality is covered through subscriptions, my proposal arguably
> doesn’t cause a problem.
>
>
>
>
> baffles me. I’m not sure what you mean by “this functionality is covered
> through subscriptions”. Tick batching wasn’t covered through signals (the
> closest predecessors of subscriptions), and isn’t covered through
> subscriptions (or at all!) right now.
>
>
> Specifically and relatedly, concerning this:
>
>
>
>
> The special behavior for tick wasn’t particularly documented for the 0.16
> Effects module and isn’t really documented for the 0.17+ AnimationFrame
> module.
>
>
>
>
> I should clarify that the tick batching trick as existed in the 0.16
> Effects module is *not implemented* for Elm 0.17+. Apparently since gamey
> stuff is not anymore in Elm’s focus, Evan didn’t bring the “first ever
> effect manager” over to the new world when effect managers as such became a
> thing.
>
>
> (Did I indicate previously that tick batching as existed before is a thing
> currently in core or other 0.17/0.18 packages? I don’t think so. I was
> only bringing it up as a thing that can be done with effect managers and
> benefits from, maybe even is absolutely dependent on, having separate
> concepts of Task and Cmd. To decide about maintaining that latter stance,
> will require digesting your material more fully.)
>
>
> ​
>
> 2016-12-11 21:26 GMT+01:00 Mark Hamburg <mhamburg...@gmail.com>:
>
> Since I wasn't proposing to get rid of subscriptions and since this
> functionality is covered through subscriptions, my proposal arguably
> doesn't cause a problem. But that's just getting through the loophole of
> this specific example to dodge this particular case, so let me see if I can
> get straight what the special property is that we need to preserve if we
> were still trying to implement a tick command in the same manner of the
> 0.16 tick effect. (It's worth noting as a side note that in 0.16, all
> effects other than tick were tasks, so obviously tasks are close to
> covering the role of commands — née effects — but tick may point to extra
> wrinkles.) I'm not going to assume a constraint by the current task
> implementation, but any revised implementation has to have a clear behavior
> in conjunction with the existing task APIs since its those APIs that make
> tasks an attractive alternative to commands.
>
> The special behavior for tick wasn't particularly documented for the 0.16
> Effects module and isn't really documented for the 0.17+ AnimationFrame
> module. Am I correct that the concern is that when the animation frame
> "arrives":
>
>
>1. We run all of the update functions before actually calling the view
>function; and
>2. Any tick effects that result from those updates will be batched
>together for the next animation frame
>
> Was there anything else that I'm missing?
>
> The first point means that any implementation is going to have to be built
> in conjunction with the Elm runtime since coordinating with the call of the
> view function requires knowledge of when and how the view function gets
> run. But since the whole point of this is to coordinate with the view
> function that shouldn't be surprising nor is it particularly odd. It does
> mean that my simple example using port tasks wouldn't work because it
> wouldn't enjoy that coordination, but extra requirements add extra
> implementation details.
>
> So, what we want is that we can divide time up with a series of animation
> frame events and at each animation frame event, we want to start a new
> epoch for collecting tick effects, run the updates driven by all effects
> collected for the previous epoch, and then do the view rendering. A naive
> implementation will just keep listening for all animation frames. A more
> sophisticated implementation will take steps to shutdown that observation
> when it is no longer necessary.
>
> The vague handwaving in the above is seemingly around what it means to say
> "run the updates driven by all effects collected for the previous epoch".
> In particular, how does this interact with task chains built using andThen,
> etc.? I am g

Re: [elm-discuss] Re: [elm-dev] Re: 0.17 Tasks vs Cmds

2016-12-11 Thread Mark Hamburg
I get uncomfortable when I wave my hands too much, so here is a more
concrete version of the task logic as sketched out in Lua. You can skip
this unless you too were bothered by my handwaving in the previous message.

Essentially, tasks are objects that can be invoked and we use different
kinds of invocations for different kinds of tasks. I've simplified to
assume only results rather than errors or results. There are two queues of
functions to execute. The immediate queue is used purely to deal with the
general rule that it's bad to invoke a callback immediately within
imperative code. So, instead we push the response onto a queue that is
drained essentially as part of any processing that starts work. The
deferred queue is for andThen computations where we are producing a series
of tasks representing extra work to do. This queue gets drained as time and
other events in the system allow.

function Succeed:invoke( fn )
enqueueImmediate( function() fn( self._value ) end )
end

function Map:invoke( fn )
self._input:invoke( function( result ) fn( self._fn( result ) ) )
end

function AndThen:invoke( fn )
self._input:invoke( function( result )
enqueueDeferred( function() self._fn( result ):invoke( fn ) )
end )
end


An update cycle produces some tasks. For each of those tasks, we call
task:invoke(
updateWithMessage ) where updateWithMessage will run one round of the
update cycle:

function updateWithMessage( message )
local updateResult =
update( message, model )
model = updateResult.model
for i = 1, #updateResult.tasks do
updateResult.tasks[ i ]:invoke( updateWithMessage )
end
drainImmediateQueue() -- will return immediately if already draining
end



So, in the context of the tick logic, the tick task would add functions to
the tick pool:

function Tick:invoke( fn )
tickPool[ #tickPool + 1 ] = fn
requestAnimationFrameIfNecessary()
end

The animation frame event then does the following:

function processTicks( time )
local oldTickPool = tickPool
tickPool = { }
for i = 1, #oldTickPool do
local fn = oldTickPool[ i ]
enqueueImmediate( function() fn( time ) end )
end
drainImmediateQueue() -- run the immediate queue until empty
end


This results in all of the outstanding tick event invocation callbacks
getting queued for execution with the current time. Ones that are on an
andThen free path back to the updateWithMessage will result in those
updates getting run. Those on paths involving andThen will result in work
being put on the deferred queue.

Looking at this implementation sketch, it even becomes clear that the
deferred queue is non-essential. It exists to reduce the amount of work we
do while processing an animation frame or between processing external
messages. What it points to in general is that when processing ticks, we
want to control when the updates they produce get run and not let them get
stuck behind everything else in the message queue — though even that is
maybe not a bad thing, we could argue that we should process all incoming
updates before rendering an animation frame.

Mark

On Sun, Dec 11, 2016 at 12:26 PM, Mark Hamburg <mhamburg...@gmail.com>
wrote:

> Since I wasn't proposing to get rid of subscriptions and since this
> functionality is covered through subscriptions, my proposal arguably
> doesn't cause a problem. But that's just getting through the loophole of
> this specific example to dodge this particular case, so let me see if I can
> get straight what the special property is that we need to preserve if we
> were still trying to implement a tick command in the same manner of the
> 0.16 tick effect. (It's worth noting as a side note that in 0.16, all
> effects other than tick were tasks, so obviously tasks are close to
> covering the role of commands — née effects — but tick may point to extra
> wrinkles.) I'm not going to assume a constraint by the current task
> implementation, but any revised implementation has to have a clear behavior
> in conjunction with the existing task APIs since its those APIs that make
> tasks an attractive alternative to commands.
>
> The special behavior for tick wasn't particularly documented for the 0.16
> Effects module and isn't really documented for the 0.17+ AnimationFrame
> module. Am I correct that the concern is that when the animation frame
> "arrives":
>
>
>1. We run all of the update functions before actually calling the view
>function; and
>2. Any tick effects that result from those updates will be batched
>together for the next animation frame
>
> Was there anything else that I'm missing?
>
> The first point means that any implementation is going to have to be built
> in conjunction with the Elm runtime since coordinating with the call of the
> view function requires knowledge of when and how the view function gets
> run. But since the whole point of this is to coordinate with the view
> function that shouldn't be sur

Re: [elm-discuss] Re: [elm-dev] Re: 0.17 Tasks vs Cmds

2016-12-11 Thread Mark Hamburg
Since I wasn't proposing to get rid of subscriptions and since this
functionality is covered through subscriptions, my proposal arguably
doesn't cause a problem. But that's just getting through the loophole of
this specific example to dodge this particular case, so let me see if I can
get straight what the special property is that we need to preserve if we
were still trying to implement a tick command in the same manner of the
0.16 tick effect. (It's worth noting as a side note that in 0.16, all
effects other than tick were tasks, so obviously tasks are close to
covering the role of commands — née effects — but tick may point to extra
wrinkles.) I'm not going to assume a constraint by the current task
implementation, but any revised implementation has to have a clear behavior
in conjunction with the existing task APIs since its those APIs that make
tasks an attractive alternative to commands.

The special behavior for tick wasn't particularly documented for the 0.16
Effects module and isn't really documented for the 0.17+ AnimationFrame
module. Am I correct that the concern is that when the animation frame
"arrives":


   1. We run all of the update functions before actually calling the view
   function; and
   2. Any tick effects that result from those updates will be batched
   together for the next animation frame

Was there anything else that I'm missing?

The first point means that any implementation is going to have to be built
in conjunction with the Elm runtime since coordinating with the call of the
view function requires knowledge of when and how the view function gets
run. But since the whole point of this is to coordinate with the view
function that shouldn't be surprising nor is it particularly odd. It does
mean that my simple example using port tasks wouldn't work because it
wouldn't enjoy that coordination, but extra requirements add extra
implementation details.

So, what we want is that we can divide time up with a series of animation
frame events and at each animation frame event, we want to start a new
epoch for collecting tick effects, run the updates driven by all effects
collected for the previous epoch, and then do the view rendering. A naive
implementation will just keep listening for all animation frames. A more
sophisticated implementation will take steps to shutdown that observation
when it is no longer necessary.

The vague handwaving in the above is seemingly around what it means to say
"run the updates driven by all effects collected for the previous epoch".
In particular, how does this interact with task chains built using andThen,
etc.? I am going to make a distinction between two ways to specify
successor computation on a task. In one case with map the results or the
error coming from the task to produce a new result or error. In the other,
we map the results or the error coming from the task to produce a new task.
I would argue that the first category is what leads to actual messages for
the model. The second can be viewed as making no changes to the model but
queueing new task executions.

So, how could this work in a task-based scenario? I'm going to speak of
tasks initiating and resolving to distinguish between when they have code
invoked v when they deliver values.

When a tick task initiates, it adds itself to the set of tick task
executions for the current tick epoch.

When we receive an animation frame call, we do the following:

   1. We grab the contents of the tick epoch set and reset the set to empty
   2. For each of the tick executions in the tick epoch set grabbed in (1),
   we resolve the execution using the current time. This means running down
   the network of tasks chained onto the executions. For cases where we map
   the result or error to a new result or error, we do so and keep working
   down the chain. For cases where we map the result or error to a new task,
   we queue that task for execution.
   3. We execute the view function.

In this way, we deliver all of the updates that are simply dependent on the
tick event or a mapping thereof while initiating any further computations
that were waiting for the tick event.

The other piece of concern is how task queueing works and when tasks get to
execute. I would probably go for a structure on the task queue in which it
is also divided into epochs. We process all of the tasks within an epoch.
Any tasks produced during this processing as a result of andThen, etc. go
in the next epoch. All tasks produced during an update go in the current
epoch which we process at the end of the update. This design keeps chains
of tasks from blocking other update processing. We could go further and
pull tasks generated by tasks off of a queue that executes even more
incrementally. The key point is that all of the tasks from an update get
initiated immediately following the update and tasks initiated from other
tasks happen as we have time to process them.

In the case of ticks, this means that a tick task that initiates 

Re: [elm-discuss] Re: [elm-dev] Re: 0.17 Tasks vs Cmds

2016-12-10 Thread Mark Hamburg
I don't think this needs to eliminate subscriptions. Subscriptions do
represent a different sort of concept. The problem with tasks and commands
is that they represent concepts that greatly overlap. I used to describe
this to coworkers who questioned it as being two concepts needed to cover
what was really one and a quarter concepts worth of material. But as this
thread got me thinking about it — spurred on also by my separate
frustration when asked by coworkers about how to do something that would
require chaining commands because the functionality hadn't been exposed as
tasks — I realized that it doesn't take much to expand tasks to cover what
commands now cover thereby eliminating the why are the two things to cover
seemingly the same territory question.

Mark

(*) I will say that I worry about the efficiency of subscriptions since my
understanding is that they are updated after every update cycle, but that's
a separate matter about how exactly subscriptions work and not about
whether they could be subsumed by something else.

On Sat, Dec 10, 2016 at 3:11 PM, Nick H <falling.maso...@gmail.com> wrote:

> So in your vision, it sounds like subscriptions would go away as well? Or
> would they become an abstraction for some sort of task port interaction?
>
> On Sat, Dec 10, 2016 at 2:34 PM, Mark Hamburg <mhamburg...@gmail.com>
> wrote:
>
>> In the case of ticks, what I gather from a read through of the code that
>> it does is guarantee that all of the tick requests placed between animation
>> frame strobes will all be delivered at the next animation frame strobe. Is
>> that a correct read?
>>
>> If so, in a task based world, what it would call for is a function of the
>> form:
>>
>> tick : Task Never Time
>>
>>
>> Remember that we can pass a task off to the runtime system and it will
>> run each time we pass it off, so while this declaration defines a
>> statically created task, it can be used repeatedly to get different ticks.
>> (If I am wrong about this aspect of how tasks work, that would change some
>> of this though it could be adapted to the change and it would be an
>> interesting addition to the strength of tasks as essentially being promises
>> for work to be done rather than being a way to represent work to be done.)
>>
>> Now, how, would we implement batching?
>>
>> Let's assume that as a replacement for commands, we gain the ability to
>> create task ports:
>>
>> port tick : Task Never Time
>>
>>
>> Or if we have to make them all be functions for consistency:
>>
>> port tick : () -> Task Never Time
>>
>>
>> Remember though that we could then just call this function once to get a
>> reusable task.
>>
>> What happens when we execute a port task? It isn't the task that resolves
>> but rather the execution of the task so initiating execution of a task
>> creates a task execution in the runtime. In the case of port tasks, the
>> proposal that's been floated — first by others but I like it — is that the
>> underlying JavaScript code would be invoked and expected to return a
>> promise which when resolved would resolve the task execution and feed into
>> whatever follows next.
>>
>> But now we see that tick batching is just a matter of caching the
>> outstanding tick promise and clearing this promise when the requested
>> animation frame arrives. The net execution logic is essentially the same,
>> but if anything it's simpler than what was needed for Elm 0.16.
>>
>> In terms of 0.17+ effects managers, this is basically just a lifting of
>> the JavaScript code into Elm. The command values that effects managers
>> construct could be wrapped inside of tasks and those values would be
>> delivered to the effects manager for further processing when the task was
>> executed.
>>
>> So, no, tasks as currently implemented aren't sufficient to replace
>> commands — if only because we have ports that can generate commands and we
>> don't have ports that can generate tasks — but my point is that the task
>> system could be extended slightly and without additional intellectual
>> complexity to cover what commands cover and Elm could thereby drop from two
>> concepts to one.
>>
>> Mark
>>
>> P.S. One area of complexity: Since tasks are just data, if you take the
>> same task value and then chain two things off of it via either Task.map
>> or Task.andThen and then bring them back together for execution, does
>> the underlying task get run once or twice? I can define runtime models that
>> make sense both ways. This doesn't come up with commands because they don't
>> allow o

Re: [elm-discuss] Re: [elm-dev] Re: 0.17 Tasks vs Cmds

2016-12-10 Thread Mark Hamburg
In the case of ticks, what I gather from a read through of the code that it
does is guarantee that all of the tick requests placed between animation
frame strobes will all be delivered at the next animation frame strobe. Is
that a correct read?

If so, in a task based world, what it would call for is a function of the
form:

tick : Task Never Time


Remember that we can pass a task off to the runtime system and it will run
each time we pass it off, so while this declaration defines a statically
created task, it can be used repeatedly to get different ticks. (If I am
wrong about this aspect of how tasks work, that would change some of this
though it could be adapted to the change and it would be an interesting
addition to the strength of tasks as essentially being promises for work to
be done rather than being a way to represent work to be done.)

Now, how, would we implement batching?

Let's assume that as a replacement for commands, we gain the ability to
create task ports:

port tick : Task Never Time


Or if we have to make them all be functions for consistency:

port tick : () -> Task Never Time


Remember though that we could then just call this function once to get a
reusable task.

What happens when we execute a port task? It isn't the task that resolves
but rather the execution of the task so initiating execution of a task
creates a task execution in the runtime. In the case of port tasks, the
proposal that's been floated — first by others but I like it — is that the
underlying JavaScript code would be invoked and expected to return a
promise which when resolved would resolve the task execution and feed into
whatever follows next.

But now we see that tick batching is just a matter of caching the
outstanding tick promise and clearing this promise when the requested
animation frame arrives. The net execution logic is essentially the same,
but if anything it's simpler than what was needed for Elm 0.16.

In terms of 0.17+ effects managers, this is basically just a lifting of the
JavaScript code into Elm. The command values that effects managers
construct could be wrapped inside of tasks and those values would be
delivered to the effects manager for further processing when the task was
executed.

So, no, tasks as currently implemented aren't sufficient to replace
commands — if only because we have ports that can generate commands and we
don't have ports that can generate tasks — but my point is that the task
system could be extended slightly and without additional intellectual
complexity to cover what commands cover and Elm could thereby drop from two
concepts to one.

Mark

P.S. One area of complexity: Since tasks are just data, if you take the
same task value and then chain two things off of it via either Task.map or
Task.andThen and then bring them back together for execution, does the
underlying task get run once or twice? I can define runtime models that
make sense both ways. This doesn't come up with commands because they don't
allow one to build more complex arrangements and it only matters from a
performance standpoint if the task operation is functional. My inclination
would be to say that you get different executions of the task for each time
it is reached in a traversal of the graph and if you don't want that you
should structure your graph so it can only be reached via one path.

On Sat, Dec 10, 2016 at 11:52 AM, Janis Voigtländer <
janis.voigtlaen...@gmail.com> wrote:

> Those are Elm 0.16 effects are something totally different. There is no
>> reason why tick tasks couldn't be batched in their execution.
>
> I disagree. I said I’m not authoritative, and meant that I can’t speak for
> *all* the possible reasons that Task and Cmd cannot be unified into one
> concept. But what I can say is:
>
>- Elm 0.16 effects are not something totally different. In fact, the
>Effects type from that package is the direct predecessor of the Cmd
>type, and the implementation of the “tick batching trick” was the first
>nontrivial effect manager (though that concept didn’t have a name back
>then). If you can substantiate the claim that 0.16’s Effects and
>0.17’s Cmd type constructors are totally different, I would be
>interested to hear the argument.
>- I was the person who implemented the “tick batching trick” back
>then. I can tell from that experience that to make it work, an abstraction
>was needed (but preexisting, not “invented” by me) that absolutely mustn’t
>support an andThen operation like Task does. So on that specific
>count, I can with a bit of authority contradict your assertion that there
>is no reason why tick tasks couldn’t be batched (with the same quality as
>Effects/Cmds can).
>
> ​
>
> --
> 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, 

Re: [elm-discuss] Re: [elm-dev] Re: 0.17 Tasks vs Cmds

2016-12-10 Thread Mark Hamburg
Those are Elm 0.16 effects are something totally different. There is no
reason why tick tasks couldn't be batched in their execution.

There are certainly things that Elm 0.17 and 0.18 are doing in effects
managers that aren't feasible with tasks right now because tasks are in a
sense too primitive, but basically what effects managers are doing is
serving as a level of indirection to route commands to other Elm code to
decide how to process them. I could imagine a similar notion of effects
manager tasks that get handed to the appropriate effects manager for
eventual fulfillment. Or instead of wrapping tasks inside of commands using
Task.perform, wrap the effects manager "command" construct inside of a task
and have execution of the task feed the underlying "command" to the effects
manager.

Mark

On Sat, Dec 10, 2016 at 10:58 AM, Janis Voigtländer <
janis.voigtlaen...@gmail.com> wrote:

> You probably already suspect as much, but anyway: I think (and I’m not
> authoritative at that) that the following part is the crux of the matter.
>
> Commands tie into the effects manager system but that’s at this point
> still an undocumented portion of Elm and I don’t see why effects managers
> could not also work with tasks.
>
> Do you have real reason to believe that effect managers could work with
> tasks? That you don’t see why not seems to be a consequence of you not
> seeing any information about their internals at all, right?
>
> If you were told that indeed effect managers cannot work as well with
> tasks (for example, that the “batching of ticks” trick mentioned in the
> documentation of old http://package.elm-lang.org/
> packages/evancz/elm-effects/2.0.1/Effects#toTask would not be possible),
> would that make you retract the proposal to have only Task, instead of
> Task and Cmd?
> ​
>
> --
> 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.
>

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


  1   2   3   >