
Tinholes – performant, strongly typed lenses in Clojure - luu
http://blog.podsnap.com/tinhole.html
======
tel
This is exciting. Lenses are really powerful and ought to be used in more
languages to accompany immutable data types. It'd be nice to see if this
technique can generalize to traversals and prisms as well. In practice, I use
those two in nearly any lensy computation.

Using macros to pre-compile the lenses is clever, but feels like a hack around
typed-clojure instead of being aligned to it. All of the information needed to
determine a lens' action is available at compile time even prior to expansion.
Can a van Laarhoven representation be made in typed-clojure that recovers this
information?

> _type-safe, efficient, concise, idiomatic and flexible handling of deeply
> nested data structures, and that 's what we got. Prima facie, these were
> unreasonable requests - it's not as though other languages were lining up to
> answer them_

and since the line was crossed: yes, other languages are exactly lining up to
answer all of those. You don't even have to burn-in the choice of lens. It's
exciting to see this technology developing all around, but it'd also be nice
to see it with a bit more humility.

~~~
podsnap
I apologize for my miscommunication and ignorance. First, the bragging was
supposed to be on behalf of the Clojure ecosystem rather than myself. Second,
while I am aware of the standard lens implementations in Haskell and Scalaz, I
didn't see that either dealt nicely with intra-path transformations, and the
Scalaz version didn't seem very concise. If there are more examples, or if I'm
wrong about these, I would love to learn more. I agree that the interaction
with typed Clojure is not ideal, but at least there's an interaction of some
sort, albeit possibly a "hack." Googling "van Laarhoven" has led me to a few
hours of reading material and to SPJ's talk, so thanks for that...

~~~
tel
Could you demonstrate a simple example of the intra-path transformation? I am
not sure that I see exactly how it should be implemented, but so long as it
isn't a lens law violation I think you can do it in Haskell's lens system at
least.

~~~
podsnap
I was thinking of setting ```:c``` in ```{:a {:b "{:c 5}"}}```. More
generally, a leaf in the container tree that is not itself a container but can
be converted to and from one. I need to play more with
[http://hackage.haskell.org/package/lens](http://hackage.haskell.org/package/lens),
but I'd certainly appreciate a shortcut to enlightenment...

~~~
tel
So there are a few things going on here

    
    
        1. Focusing on "the subtree" instead of "the value
           at the subtree"
        2. Working with data types like `{:a {:b {:c 5}}}` is
           somewhat uncommon in Haskell (too little information
           gets projected into the types)
        3. Doing "along the way parsing"
    

Each of those are fine to do in Haskell and I could work up an example.
Perhaps the best domain for this is using the lens-aeson[0] package since your
data type is not so different from JSON. Here you can use the _JSON prism to
do your "along the way parsing" (the failure mechanism of prisms catches
failed parses naturally). You can also focus on whole subtrees naturally
(since the JSON Value type is just a sum over subtrees and values all
together, so the natural parametricity distinction is lost).

So I'd look at [0] for a wealth of examples in that vein. I'd also look into
zipper lenses. They were removed in more recent versions (I think anticipating
splitting them out into another package) but they're available in the 3.*
series [1].

[0] [http://hackage.haskell.org/package/lens-
aeson](http://hackage.haskell.org/package/lens-aeson) [1]
[http://hackage.haskell.org/package/lens-3.10.1/docs/Control-...](http://hackage.haskell.org/package/lens-3.10.1/docs/Control-
Lens-Zipper.html)

~~~
podsnap
Yes, lens-aeson looks pretty damn close. I've got a bunch of reading to do.

The existence of zipper lenses catches me by surprise, as I have been
frequently directed at a stackoverflow [0] response on the difference between
the two...

[0] [http://stackoverflow.com/questions/22094971/what-are-the-
dif...](http://stackoverflow.com/questions/22094971/what-are-the-differences-
between-lenses-and-zippers/22097113#22097113)

~~~
tel
I'm the author of the non-accepted answer to that question. For what it's
worth, I think cgrand's is weak in describing both zippers and lenses, but
ultimately lands on the wrong distinction.

------
podsnap
Sorry about "performant," everyone. After years of being mocked as a pedant
for avoiding the word (ok, there may have been other reasons), I decided to
dip a toe in the descriptivist waters. Maybe it's too soon. I toyed with
"fast" in the title, but that could be taken as referring to ease of use. I'll
spend the next few hours trying to come up with a better title.

------
podsnap
Ok, I managed to get a van Laarhoven representation in typed Clojure, though
it wasn't exactly a smooth experience.
[http://blog.podsnap.com/vanhole.html](http://blog.podsnap.com/vanhole.html)

------
lkrubner
This seems to be the core of the idea, which I like a great deal:

"Type-checking is somewhat difficult with the current implementations of ph-
whatever, as, intuitively, it would be with anything implemented as a
recursive function that might consume and return values of different types at
different levels of the stack. "

So the goal is to enable TypedClojure to work in some functions, such as
assoc-in, that are recursive and difficult to type.

------
beagle3
Disclaimer: I don't know Haskell.

But I did read the article - do I understand correctly that lenses are more or
less equivalent to the Common Lisp getf constructs?

------
nodata
Performant?

~~~
rubiquity
I'm not sure if you're asking whether this library performs well or are
picking on the use of the made-up-for-engineer's-use word "performant." I'm
going to assume the latter. I think it's an OK word to use. It's a succinct
way of saying something performs well. We programmers tend to have a deep
history in stealing terms from other industries and butchering their meaning
(orthogonal, impedance mismatch), it's about time we make up some of our own!

~~~
delluminatus
Well, I have no problem with making up words, but I feel like mentioning that
there is an even more concise term that could be used: "fast".

Although this word doesn't have a scientific gleam or a stamp of enterprise
approval, it is actually _more_ specific than "performant". Technical words
are nice but sometimes they just serve to hide details. All that glitters is
not gold.

~~~
solipsism
* it is actually more specific than "performant"*

I disagree. See this use of 'fast' in a submission, for example:
[https://news.ycombinator.com/item?id=7132044](https://news.ycombinator.com/item?id=7132044)

What does "fast" mean there? It could mean the development environments are
performant. Or it could mean they're quick to implement or set up. I believe
the latter is what is intended, but I can't be sure from the submission or
even the article, because the word "fast" is not very specific. In this
context, the word "performant" would have been much more clear.

Language is fuzzy and malleable and subjective. People shouldn't be so quick
to lay down declarations of approved or preferred words. And to chide someone
for using a word that hasn't made it to the dictionary yet is tantamount to
declaring that we should freeze English and never change it (referring to the
great-grandparent post here).

