Difficulty learning Elm

260 views
Skip to first unread message

J. E. Marca

unread,
Sep 27, 2016, 1:40:05 AM9/27/16
to Elm Discuss
Hi all,

I have a moderately complicated JSON object.  A sample looks like:

```
{
  "118_192": {
    "Cloverdale P": {
        "sum_lane_miles": 0,
        "sum_single_unit_mt": 0,
        "sum_vmt": 57,
        "sum_combination_mt": 0
      }
    }
}
```

Thousands of such top level entries, with a variable number of secondary entries, and two different types of tertiary entries depending on the "type" of the second entry.  I'm debating between a simple nested dict approach, and a more complicated nested dict of two alternative object types, but I can't get past Go with the repl in order to test out my ideas.

First, the most simple case, I can decode this with nested Dictionaries

What I did in the repl is:

```

import Json.Decode as Json exposing (..)
import Dict exposing (..)

inputString = """{  "118_192": {    "Cloverdale P": {      "sum_lane_miles": 0,      "sum_single_unit_mt": 0,      "sum_vmt": 57,      "sum_combination_mt": 0    },    "CO P": {      "sum_lane_miles": 0,      "sum_single_unit_mt": 0,      "sum_vmt": 43,      "sum_combination_mt": 0    }      }}"""

gridVolumes = dict ( dict (dict float))
dataDict = decodeString gridVolumes inputString
```

But that last line is a wild guess.  What I want to do is get "something" I can use as a dictionary, but Elm is giving me two things...a Result object and the dictionary.

```
> dataDict
Ok (Dict.fromList [("118_192",Dict.fromList [("CO P",Dict.fromList [("sum_combination_mt",0),("sum_lane_miles",0),("sum_single_unit_mt",0),("sum_vmt",43)]),("Cloverdale P",Dict.fromList [("sum_combination_mt",0),("sum_lane_miles",0),("sum_single_unit_mt",0),("sum_vmt",57)])])])
    : Result.Result
        String
        (Dict.Dict String (Dict.Dict String (Dict.Dict String Float)))
>
```

How do I strip off the "Result" in the repl so I can touch the dictionary and play with various types of Dict.get commands?

Obvious to me that I'm just not getting a fundamental concept of the language, but I can't find the right point of view so far in the docs I've read...for example, the JSON help page (https://guide.elm-lang.org/interop/json.html) never actually seems to *assign* the result of running a JSON parser to a value, and the JSON library documentation has fragements of code, but no complete worked examples one can reproduce in the repl.

Any advice or pointers to docs I should read or reread would be appreciated.  Or just a simple "you're doing X wrong do Y instead to get access to the Dict String (Dict String (Dict String Float))) thing" would be welcome too!

Regards,
James

Peter Damoc

unread,
Sep 27, 2016, 3:04:14 AM9/27/16
to Elm Discuss
When you do something that can fail in some way, Elm gives you back a type that has the failure covered so that you can treat it properly. 
The two most frequently used types are
- Result where you either have Ok someType  OR  Err someFailureType 
- Maybe where you either have Just someType OR Nothing 

In both cases, if you are 100% sure that the operation cannot fail or you don't want to cover the fail case, you can provide a default value and unpack the type 

Result.withDefault defaultValue someResult 

or 

Maybe.withDefault defaultValue someMaybe


You can read more in the Error handling section of the guide:
https://guide.elm-lang.org/error_handling/




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



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

J. E. Marca

unread,
Sep 27, 2016, 11:35:46 AM9/27/16
to Elm Discuss
Hi thanks.  I was missing the Result library entirely!


On Tuesday, September 27, 2016 at 12:04:14 AM UTC-7, Peter Damoc wrote:
When you do something that can fail in some way, Elm gives you back a type that has the failure covered so that you can treat it properly. 
The two most frequently used types are
- Result where you either have Ok someType  OR  Err someFailureType 
- Maybe where you either have Just someType OR Nothing 

In both cases, if you are 100% sure that the operation cannot fail or you don't want to cover the fail case, you can provide a default value and unpack the type 

Result.withDefault defaultValue someResult 

or 

Maybe.withDefault defaultValue someMaybe


You can read more in the Error handling section of the guide:
https://guide.elm-lang.org/error_handling/



...

J. E. Marca

unread,
Sep 27, 2016, 11:43:08 AM9/27/16
to Elm Discuss
...


On Tuesday, September 27, 2016 at 12:04:14 AM UTC-7, Peter Damoc wrote:

...
 
You can read more in the Error handling section of the guide:
https://guide.elm-lang.org/error_handling/



I read that on my first pass through the guide, and just re-read it.  What I don't see in there is a simple one-liner to get results in a repl when I know the result is okay --- it's a repl, I can see the result with my eyes.  But after looking up the Result library you mentioned, now instead of the long case statement (with the super annoying backslash-end-of-line thing for multiline entries), I can use a much simpler Result.withDefault.



Nick H

unread,
Sep 27, 2016, 2:38:59 PM9/27/16
to elm-d...@googlegroups.com
It seems like an oversight that the guide doesn't mention withDefault, considering that's one of the most important functions in the Maybe & Result libraries.

I think maybe the guide is best used as a supplement to the core documentation. None of the modules are too big... if you haven't yet, I would definitely recommend browsing the docs for whatever modules you're using!

Totally agree that multi-line expressions are super annoying in the REPL. For playing around with code, I've found the online editor to be much more useful.

Another thing you could try would be to write your longer definitions in a file:

module Foo exposing (..)


import Json.Decode as Json exposing (..)
import Dict exposing (..)

inputString = """{  "118_192": {    "Cloverdale P": {      "sum_lane_miles": 0,      "sum_single_unit_mt": 0,      "sum_vmt": 57,      "sum_combination_mt": 0    },    "CO P": {      "sum_lane_miles": 0,      "sum_single_unit_mt": 0,      "sum_vmt": 43,      "sum_combination_mt": 0    }      }}"""

gridVolumes = dict ( dict (dict float))
dataDict = decodeString gridVolumes inputString

 and then load the file into the REPL using an import statement.

> import Foo exposing (..)
> dataDict



Leroy Campbell

unread,
Sep 27, 2016, 7:14:21 PM9/27/16
to Elm Discuss
Rather than decode to nested Dict types, you could create types that represent your domain better (assuming the underlying JSON is well-structured). You can also use `andThen` to decode based on some field in your objects.
Reply all
Reply to author
Forward
0 new messages