If decoding json in Elm is considered hard, I'd recommend checking out miso (https://github.com/dmjio/miso), a Haskell re-implementation of the Elm arch. It has access to mature json libraries like aeson for that sort of thing, along with mature lens libraries for updating your model. Here's an example of decoding json with GHC.Generics using typeclasses.
https://github.com/dmjio/miso/blob/master/examples/xhr/Main....
You don't need to switch a whole language because of JSON decoding. There are many tools that exist to aid you write JSON decoders in Elm. The language is not just about the architecture -- you can implement the architecture in any language, as Redux has proven. What people like about Elm is the compiler and design philosophy that radiates through the entire community. Switching to Haskell won't give you that, as the Haskell community has different priorities.
I am kinda waiting for Purescript to mature a tiny bit more in this regard, because it seems that they have something special brewing there, with their polymorphic record type and interesting take on type-level programming.
Because this [1], even though it seems to be just a experiment so far, looks really good.
I.e: doing
type MyTestStrMap =
{ a :: Int
, b :: StrMap Int
}
and then just calling
let result = handleJSON """
{ "a": 1, "b": {"asdf": 1, "c": 2} }
"""
let newResult = doSomething (result:: Either MultipleErrors MyTestStrMap))
is kinda all I ever wanted in these haskell inspired languages?
This is very cool. The example apps are relatively slow to load compared to the equivalent in some other frameworks (my favorite is Mithril for an idea of how small/fast these can get).
Was wondering whether it might be a slow server, but the app.js for the TodoMVC appears to be over a megabyte (1.21 MB, have a 4000 line Mithril app which is 500k uncompressed). What's up with that?
ghcjs is a pretty heavyweight environment. It's actually translating the compiled core IR from GHC into JavaScript, and including a port of GHC's runtime system.
It can run basically any Haskell library. That includes the ability to run multithreaded Haskell code -- the JS RTS includes a scheduler. You also get Software Transactional Memory. Lazy evaluation works just as usual -- and so on.
The tradeoffs become worth it when you have a sufficiently valuable base of Haskell code that you want to run in the browser, and when your users aren't very constrained by page load time. Say, if you have some complicated tricky logic that you don't want to rewrite in another language, but you want to use it in your web app.
Aeson is SLOOW compared to 'JSON.parse' + GHCJS ffi. You lose a bit of correctness (JSON.parse can decode numbers only to the JS precision, ie. 53bits, while Aeson supports arbitrary precision through Scientific), and ability to decode streams in constant memory. But these are features which you most likely don't need in a web app.
There’s no reason to use genericParseJSON here, you can just write “instance FromJSON APIInfo”. Or leave the instance declaration as it is and safely rename your record fields to e.g. currentUserUrl instead of current_user_url.
The purpose of the camelTo function is to convert “camelCaseExample” into e.g. “camel_case_example” by passing ‘_’ as the first argument. But the APIInfo data structure already uses record fields with underscores in them.
Here are some JSON tools for Elm:
- json-to-elm http://json2elm.com
- swagger-elm https://github.com/ahultgren/swagger-elm/
- elm-graphql https://github.com/jahewson/elm-graphql, https://github.com/jamesmacaulay/elm-graphql
- elm-export https://hackage.haskell.org/package/elm-export