Lisplog

Blogging in Lisp

Search

Feed Aggregator Page 674

Rendered on Thu, 25 Nov 2021 18:33:57 GMT  newer latest older 

Conditional JSON decoder with optional fields

via Elm - Latest posts by @wondible Justin Love on Wed, 24 Nov 2021 14:31:45 GMT

This is a classic case for Json.Decode.andthen

e.g. (untested)

import Json.Decode exposing (...)

decodeRecordType : Decoder RecordType
decodeRecordType =
  (at ["type", "name"] string)
    |> andThen decodeRecordTypeDetails

decodeRecordTypeDetails : String -> Decoder RecordType
decodeRecordTypeDetails name =
  case name of
    "bed" -> decodeBed
    "chair" -> decodeChair
    "stool" -> succeed Stool
    _ -> fail ("unknown record type: " ++ name)

Conditional JSON decoder with optional fields

via Elm - Latest posts by @ben-t on Wed, 24 Nov 2021 13:57:22 GMT

Hi all,

I have some JSON from a 3rd party API that can take a few different forms. For each response, there are

  • Shared fields which are present in every response (id, timestamp, etc)
  • There is a field type (present in every response) whose value is another JSON object with id and name keys
  • There is an additional key whose name is is the name of the type object. Some types don’t actually have any additional metadata (and thus have no extra key in the response JSON).

For example:

{
  "id": 1,
  "timestamp": "etc",
  "type": {"id": 1, "name": "chair"},
  "chair": {
    // (Chair metadata goes here)
  }
}

Or...

{
  "id": 2,
  "timestamp": "etc",
  "type": {"id": 4, "name": "bed"},
  "bed": {
    // (Bed metadata goes here)
  }
}

Or...

{
  "id": 2,
  "timestamp": "etc",
  "type": {"id": 4, "name": "stool"},
  // (no metadata)
}

Where the metadata for each type has a different shape.

This is complicated by the fact that
I could naively decode this into an Elm record with lots of optional fields:

type alias NaiveRecord =
    { id : Int
    , timestamp : Timestamp
    , recordType : NaiveRecordType
    , chair : Maybe ChairMetadata
    , bed : Maybe ChairMetadata
    , table : Maybe TableMetadata
    -- and so on...
    }

type alias NaiveRecordType =
    { id : Int,
    , name : String 
    }

However, this seems bad for a couple of reasons:

  • It makes (theoretically) impossible states possible. The relevant metadata field for each record’s type should be Just a if and only if the recordType is the corresponding one.
  • Any production code using this type will result in unnecessarily getting any metadata in/out of Maybes when we know that the value is present (or rather, if the value isn’t present, something has gone very wrong and we would like to handle that case differently!)

So, I would rather use a type like:

type Record =
    { id : Int
    , timestamp : Timestamp
    , recordType : RecordType
    }

type RecordType
    = Chair ChairMetadata
    | Bed BedMetadata
    | Table TableMetadata
    | Stool      -- Has no additional metadata
    | Bookcase   -- Has no additional metadata
    -- And so on

However, I’m not sure quite how to decode this from the JSON, as it requires checking the type's name field, and then (possibly) nesting the top level metadata field within the RecordType.

My current best guess is to use the “naive” type as an intermediate type. For example:

decodeNaiveRecord : Decoder NaiveRecord
-- i.e. relatively cookiecutter decoder with Decode.mapN or similar

fromNaiveRecord : NaiveRecord -> Decoder Record
-- i.e. succeed if "type" matches the metadata field, fail otherwise

decodeRecord : Decoder Record
decodeRecord =
    Decode.andThen fromNaiveRecord decodeNaiveRecord

I have 2 main questions that I would like help with:

  • Is my “target” type (Record) a good design for this problem or is there a better solution/pattern I should be aware of
  • If it is an acceptable design, then what is the best approach to decode the JSON into it? Is there any clear and elegant way to do so without going via an intermediate data type?

Thanks!

A process for core library fixes and improvements

via Elm - Latest posts by @gampleman Jakub Hampl on Wed, 24 Nov 2021 13:31:02 GMT

I’ll keep to poll open until the thread closes, but it seems that there is some interest, but (as I suspected) probably not enough to even pay a single person half-time.


I feel slightly demotivated to contribute to Elm, pureley out of love for it, knowing that a business that doesn’t give freely back to me is consuming it for profit

That’s not necessarily how that would work. I think a company set up like this would generally work as open-source and potentially (if the core elm team wanted) could even send PRs to the core repos. The thing one would pay for isn’t exclusive fixes, but the knowledge that someone has your back if a show-stopping bug appears in the core library as well as easy tooling to apply those (and I suspect making that tooling seamless would be a big bulk of the work, especially as few people use the elm compiler just on its own, but rather through integrations with Webpack et al).

Such a business would inevitably act in its own interests, whilst wielding influence over something that matters to me.

Not clear to me that anyone has much influence around here outside the core Elm team. If this hypothetical company became so indispensable that it would start getting influential despite that, I think that would be a very strong signal (and note that Evan and company seem to be very interested and sensitive on the topic of corporate influence on open source) that the current maintenance model may need to be reconsidered. Conversely, if such a company went quickly out of business (or languished in obscurity), it would provide validation to the hypothesis that things are fine as they are.


I don’t think you will make money anyway

Well I wasn’t planning to be the one to run this, but I agree that it doesn’t seem to be an amazing business plan as things stand.

Working with folders

via Elm - Latest posts by @hrnxm Harun Muderizovic on Wed, 24 Nov 2021 07:10:43 GMT

As wolfadex said, your best bet is to read it as a list of files. Here is a very very rough example of what we’re doing.

Successes, and failures, in optimizing Elm's runtime performance

via Elm - Latest posts by @albertdahlin Albert Dahlin on Tue, 23 Nov 2021 20:40:51 GMT

Thank you for taking your time to write this, I enjoy reading and learning.

'let' best practices

via Elm - Latest posts by @mje on Tue, 23 Nov 2021 15:47:59 GMT

SPJ’s book is mostly about non-strict languages, whereas Elm is strict, so you can’t always apply lessons from the book to Elm.

Even if that section of the book is strictness agnostic, another aspect is that the book describes translating source code to an enhanced lambda calculus where there are no temporary variables. So even if there is such a translation step in Elm, with referential transparency, f model and newModel are interchangeable, and a good compiler ought to be able recognize repeated expression and optimize them away.

Elm-select gets a native html select variant

via Elm - Latest posts by @system system on Tue, 23 Nov 2021 15:43:30 GMT

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.

'let' best practices

via Elm - Latest posts by @dkodaj Daniel Kodaj on Tue, 23 Nov 2021 15:13:06 GMT

I don’t know why you would think that newModel is computed twice.

Section 3.2 of The Implementation of Functional Languages by Peyton Jones seems to imply that you evaluate f newModel (using the let definition from the first example above) by calculating f (complicatedTransformationOf model). I never checked how Elm actually does it.

Thanks!

'let' best practices

via Elm - Latest posts by @jfmengels Jeroen Engels on Tue, 23 Nov 2021 12:39:17 GMT

I don’t know why you would think that newModel is computed twice. Is it because you’re thinking that values are lazy like in Haskell?

Anyway, no, newModel is only computed once. FYI, this is roughly what your code compiles to in JavaScript:

function update(msg, model) {
	var newModel = complicatedTransformationOf(model);
	var cmd = someFunctionOf(newModel);
	return _Utils_Tuple2(newModel, cmd);
});

newModel is only computed once, and then it’s value is referenced/used in two places.

Your second version is pretty much the same. If anything, it might be a tad slower because you have more function calls, but it’s to a negligible degree (unnoticeable if your function isn’t computed thousands of times per second).

I don’t think you generally need to concern yourself with performance around let expressions too much. They don’t have specific performance problems.

Your first version is just fine: it’s readable and you don’t have any performance penalty in there. Keep it the way it is.

'let' best practices

via Elm - Latest posts by @dkodaj Daniel Kodaj on Tue, 23 Nov 2021 12:24:32 GMT

This is probably a highly complicated question (possibly answered elsewhere), but I find myself wondering about it a lot – what are the main performance-improving pro tips for let expressions? I’m thinking of cases like the following:

update msg model =
    let
        newModel =
            complicatedTransformationOf model

        cmd =
            someFunctionOf newModel
    in
    ( newModel, cmd )

Is newModel calculated here twice? If it is, then is it more performant to write this instead?

update msg model =
    let
        f x =
            complicatedTransformationOf x

        cmd x =
            someFunctionOf x

        g x =
            (x, someFunctionOf x)
    in
    g (f model)

Working with folders

via Elm - Latest posts by @wolfadex Wolfgang Schuster on Tue, 23 Nov 2021 12:15:58 GMT

It looks like you’d need to use HTMLInputElement.webkitdirectory - Web APIs | MDN and it’s associated property for retrieving the file list. Would likely be easiest to make a tiny custom element that relays the entries as an event.

Word of caution though, this doesn’t work with all browsers.

Working with folders

via Elm - Latest posts by @jaruji on Tue, 23 Nov 2021 11:41:30 GMT

Hey everyone,
I was wondering if someone here has some experience/idea about how to upload entire folders into an Elm app. As far as I know, this option is not supported nowhere in the File package. It is possible to upload folders with HTML input element, but they get stored somewhere in the DOM if I understand correctly (specifically at the id of the input). I would love to be able to:

  1. Get a JSON schema of the uploaded folder structure
  2. Have all the files stored in Elm be it as a List File or List String (I’m mainly interested in their content)

Would love to hear you suggestions, Thank you!

Successes, and failures, in optimizing Elm's runtime performance

via Elm - Latest posts by @robin.heggelund Robin Heggelund Hansen on Tue, 23 Nov 2021 10:43:44 GMT

I’ve just started a series of articles that details the experiments that culminated in the latest elm-optimize-level-2 release. A new article is published every day, and it will explore all of my different attempts at making the Elm runtime faster.

This link contains links to the other articles along with their publication date, it will be updated daily, so you can check it out each day to get a link to the next published article.

I hope you enjoy this just as much as I’ve enjoyed writing it =)

Error in Elm Guide

via Elm - Latest posts by @system system on Tue, 23 Nov 2021 09:04:59 GMT

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.

Elm-json fails to fetch package versions

via Elm - Latest posts by @raephee2 on Tue, 23 Nov 2021 07:23:16 GMT

The problem was an expired root cert in /etc/ssl/certs.pem (on OSX Mojave). By removing it from the file, I managed to get elm-json working again.

Updating a deeply nested array?

via Elm - Latest posts by @pit Pit Capitain on Tue, 23 Nov 2021 06:42:58 GMT

If you are always editing one node at a time, you could use a tree zipper to focus on the currently edited node. Then most of the work would be spent on moving the focus, but not on editing the current node. Maybe this is better in your use case?

Elm-json fails to fetch package versions

via Elm - Latest posts by @raephee2 on Mon, 22 Nov 2021 21:46:27 GMT

In the end, I reported the issue at elm-json’s GitHub space. According to jfmengels, it’s very likely an issue with older OSX versions.

Introducing Elm Editor - a web-based IDE for Elm programs

via Elm - Latest posts by @Viir Michael Rätzel on Mon, 22 Nov 2021 20:11:25 GMT

I implemented this at Expand loading from git repositories to support links to repository root · elm-fullstack/elm-fullstack@6c5d806 · GitHub

You can now use the link to the repository. The loading from git now also works for the URL you find in the address bar on the repository homepage. In this case, Elm Editor uses the HEAD reference from the git repository to determine the default branch.

(Meanwhile I also updated the demo instance to integrate that change)

A process for core library fixes and improvements

via Elm - Latest posts by @rupert Rupert Smith on Mon, 22 Nov 2021 16:44:09 GMT

If I think of starting a business around something, I also think, is this the business I would start if my aim was to succeed by making money?

I voted that my company will pay £0 for a maintained Elm, because I don’t think it is the best way to manage things for the benefit of all.

My reasons are:

  • I feel slightly demotivated to contribute to Elm, pureley out of love for it, knowing that a business that doesn’t give freely back to me is consuming it for profit (if you are so lucky, I don’t think you will make money anyway).

AND

  • Such a business would inevitably act in its own interests, whilst wielding influence over something that matters to me.

I don’t in any way disagree with businesses making money from Elm (if they can) from the position of being a more neutrally oriented third party, not one that controls its future maintenance and direction.

I think contributing to Elm as a package author has thus far been very rewarding. In addition to really enjoying writing those packages, I also know I have greatly multiplied the effort in what I receive back. That kind of positive cycle is what I would most want to retain about it. I also think it is the way that is most beneficial to all.

I think we are slowly working towards a fork, but I don’t see it as urgent or the next thing that should happen, since there is still a lot of scope to make improvements before that really needs to happen.

An idea I have put forward before is that a fork of it could become an Apache Foundation incubator project. That has some potential advanges:

  • Apache has been around a good while and is generally well respected.
  • They can provide hosting resources.
  • It can help with getting corporate sponsorship and act as a conduit for funding.
  • They are experienced at mentoring open source projects.
  • It helps to establish a good governance model for the long term management of a project.
  • Bus factor has to be resolved before a project can graduate from the incubator - all top-level Apache projects have multiple contributors.

Updating a deeply nested array?

via Elm - Latest posts by @Snaker on Mon, 22 Nov 2021 16:36:55 GMT

This looks great. I can’t imagine it helping performance much but at least should make the task much easier.

Oh that is exactly how I implemented variables, nice to see I am on the right track. I did leave out this part though for simplicity sake.

No, I explicitly want to modify the NumberLiteral and that is just the start. I need to be able to do all sorts of complex modifications to the AST in real time, deleting and moving nodes and so on. (If you need to know, it is similar to what the editor of the Roc programming language does, allowing you to edit the language directly in AST form. At least from what I can tell from the videos.)

I think it might be better to think about me wanting to writer an editor for a complex ToDo List with child elements or something like this, which would require similar solutions.

 newer latest older