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

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] Is a decoder the right level of abstraction for parsing JSON?

2017-03-18 Thread Kasey Speakman
Yes, but it requires me to keep decoder/encoder files, and fiddle with them
every time my types change. What a waste of time.

Using this method, I don't have to do anything extra when types change. Nor
keep extra files.

On Sat, Mar 18, 2017 at 11:43 AM Noah Hall  wrote:

> Http://json2elm.com. auto generating json "codecs" (decoders and
> encoders) has existed for more than a year already.
>
> On Friday, March 17, 2017, Kasey Speakman  wrote:
>
> Another update. I figured out how to get the encoders and decoders out of
> the ports using a native module. So I no longer have to actually send
> things across ports (still have to declare them). I can also now use Elm's
> Http module.
>
> Here's a gist of what it takes:
>
> https://gist.github.com/kspeakman/3f9521b0921b352c7d656261ec0a8fa6
>
> On Saturday, February 18, 2017 at 2:22:32 AM UTC-6, Kasey Speakman wrote:
>
> An update. I'm using the ports approach to deal with JSON (and also
> sending the HTTP request). For several months, I've had a small but
> critical app in production using that. Another project in development is
> too. In the process, I have run across two additional caveats with this
> approach.
>
>1. *Ports don't convert undefined properties to Maybe.Nothing.* It's
>an open issue from Jan 2016.
>
>For a Maybe property, the JSON must have the property present and set
>to null. Otherwise error. This is particularly annoying when you store the
>data as JSON and pass it back to the client as-is. To work around this
>issue, I either have to waste space storing nulls in the database or waste
>(CPU/response) time server-side to inject nulls in the response.
>
>2. *Cmd.map can't be used with this method.*
>Using Http module, you can use Cmd.map to take some data from the
>request and give it to the response Msg. Using ports, you can't do that.
>I've noticed this when the data is easy to provide for a request, but after
>the response comes back it is less convenient to dig out of the model (e.g.
>behind a case statement).
>
> Neither of these are blockers for me, just nuisance issues. It still beats
> maintaining codecs.
>
> I've seen rumblings about tools for code-gen'ing JSON codecs for us (maybe
> elm-format?  There also
> exists elm-swagger, but I don't use swagger.). I dunno though. Where
> possible, I tend to avoid code-gen because it's for handling a really
> tedious problem. And if the code-gen fails, then I have to handle a really
> tedious problem. (XSD/WSDL flashbacks.)
>
> All it would really take for a profound QoL improvement are a couple of
> "special" functions on Http that handle data exactly like ports do now...
> just saying.
>
> --
>
> 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/XW-SRfbzQ94/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.


Re: [elm-discuss] Is a decoder the right level of abstraction for parsing JSON?

2017-03-18 Thread Noah Hall
Http://json2elm.com. auto generating json "codecs" (decoders and encoders)
has existed for more than a year already.

On Friday, March 17, 2017, Kasey Speakman  wrote:

> Another update. I figured out how to get the encoders and decoders out of
> the ports using a native module. So I no longer have to actually send
> things across ports (still have to declare them). I can also now use Elm's
> Http module.
>
> Here's a gist of what it takes:
>
> https://gist.github.com/kspeakman/3f9521b0921b352c7d656261ec0a8fa6
>
> On Saturday, February 18, 2017 at 2:22:32 AM UTC-6, Kasey Speakman wrote:
>>
>> An update. I'm using the ports approach to deal with JSON (and also
>> sending the HTTP request). For several months, I've had a small but
>> critical app in production using that. Another project in development is
>> too. In the process, I have run across two additional caveats with this
>> approach.
>>
>>1. *Ports don't convert undefined properties to Maybe.Nothing.* It's
>>an open issue from Jan 2016.
>>
>>For a Maybe property, the JSON must have the property present and set
>>to null. Otherwise error. This is particularly annoying when you store the
>>data as JSON and pass it back to the client as-is. To work around this
>>issue, I either have to waste space storing nulls in the database or waste
>>(CPU/response) time server-side to inject nulls in the response.
>>
>>2. *Cmd.map can't be used with this method.*
>>Using Http module, you can use Cmd.map to take some data from the
>>request and give it to the response Msg. Using ports, you can't do that.
>>I've noticed this when the data is easy to provide for a request, but 
>> after
>>the response comes back it is less convenient to dig out of the model 
>> (e.g.
>>behind a case statement).
>>
>> Neither of these are blockers for me, just nuisance issues. It still
>> beats maintaining codecs.
>>
>> I've seen rumblings about tools for code-gen'ing JSON codecs for us (maybe
>> elm-format?  There also
>> exists elm-swagger, but I don't use swagger.). I dunno though. Where
>> possible, I tend to avoid code-gen because it's for handling a really
>> tedious problem. And if the code-gen fails, then I have to handle a really
>> tedious problem. (XSD/WSDL flashbacks.)
>>
>> All it would really take for a profound QoL improvement are a couple of
>> "special" functions on Http that handle data exactly like ports do now...
>> just saying.
>>
> --
> 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.