

Working on JSON with lenses and prisms - tikhonj
https://www.fpcomplete.com/user/tel/lens-aeson-traversals-prisms

======
tel
For the non-Haskeller audience, let me just copy the money quotes. This
tutorial eventually shows how we can write the following Python

    
    
        > str = '[{"someObject" : { "version" : [1, 0, 0] }}]'
        > it = json.loads(str)
        > it[0]["someObject"]["version"][1]
    

as the following Haskell

    
    
        '[{"someObject" : { "version" : [1, 0, 0] }}]' ^? 
            nth 0 . key "someObject" . key "version" . nth 1
    

while keeping type safety, composability, and purity. That's the wonderful
part. The rest is explaining a lot of how the magic works via Maybe monad
chaining and thinking about what Lenses and Prisms are.

~~~
peq
I don't see how the Haskell example is more type safe than the Python example.
In Haskell you will get None or Just a String. In Python you get an exception
or a String. For me that is equivalent, but maybe you have a different
definition of type safety?

I think without a schema for the json data we cannot make this any more type
safe.

~~~
tel
I agree completely that this example is not fully type safe---there is an
implicit, partial schema where either Python exceptions or Haskell Nothings
imply validation failure, but that's beside the point.

The example written has a lot of type resolution done implicitly by the
typeclass mechanism. It ensures that only valid lens-like combinators are
applied to the traversal chain... which is only an issue due to how far we can
flex the lens library to do other things.

A better example is the somewhat more explicit version of this code

    
    
        it ^? _JSON   . _Array  . nth 0
                      . _Object . key "someObject"
                      . _Object . key "version"
                      . _Array  . nth 1
    

Where the _JSON, _Array, nth, _Object, and key declarations must match
otherwise its a type error. Furthermore, the `nth` and `key` calls are both
just type-restricted aliases for `ix` which help to convey via types what
kinds of very general tools should be applied here.

We could also, for instance, throw another _JSON Prism into the chain to do a
nested, schema-based validation for any types which have ToJSON/FromJSON
instances.

------
Peaker
I love examples that show that with a little effort (at least when standing on
the shoulders of giants), we can have our cake (nice abstractions) and eat it
too (not lose type safety).

