8 ms·
Lens: Lenses, Folds and Traversals
- moomin 1y agoLet’s just say that if you wanted to understand lenses, this is not where you should start; and if you wanted to move to more advanced scenarios, I wouldn’t start here either.
- xtoilette 1y agowhere would you start?
- neanderzander 1y agoI found this accessible: https://academy.fpblock.com/haskell/tutorial/lens/ https://academy.fpblock.com/haskell/tutorial/lens/
- deleted 1y ago[deleted]
- wk_end 1y agoAssuming you've got experience with Javascript, read the "Motivation" section on the monocle-ts website: https://gcanti.github.io/monocle-ts/ https://gcanti.github.io/monocle-ts/
- raluk 1y agohttps://blog.jle.im/entry/lenses-products-prisms-sums.html https://blog.jle.im/entry/lenses-products-prisms-sums.html
- cosmic_quanta 1y agoWhat a great read! I had never encountered or thought about prisms before, but now it I see how useful they could be. Thank you for sharing
- KPGv2 1y agoOptics by Example by Chris Penner is good. https://leanpub.com/optics-by-example/ https://leanpub.com/optics-by-example/
- raluk 1y agoGreat exercise driven course is: https://github.com/system-f/lets-lens https://github.com/system-f/lets-lens
- ohdeargodno 1y agoA first good step is getting rid of Haskell's obscure and impenetrable syntax, and checking implementations that would be more readable. Kotlin's Arrow library hits a good middle ground between FP wizardry and readability, and their documentation on lenses are understandable for the average person: https://arrow-kt.io/learn/immutable-data/lens/ https://arrow-kt.io/learn/immutable-data/lens/ / https://arrow-kt.io/learn/immutable-data/intro/ https://arrow-kt.io/learn/immutable-data/intro/
- epgui 1y ago> Haskell's obscure and impenetrable syntax Uhhh... Haskell syntax is simpler than python's or javascript's. It's neither obscure nor impenetrable, but it sounds like it's different than what you're used to.
- HappMacDonald 1y agoHaskell has enough punctuation to make Larry Wall blush
- epgui 1y agoThey’re just regular functions, but infix.
- HappMacDonald 1y ago```Haskell -- | Flipped version of '<$>'. infixl 1 <&> (<&>) :: Functor f => f a -> (a -> b) -> f b as <&> f = f <$> as ``` "infix", "Functor", and "as" are the only words in this code. Everything else is single letters (thanks math traditions..) and punctuation. What's a <&>? <$>? ::? We've got two different kinds of arrows, => and ->. -- is obviously enough a line comment. At least I know what = means.. give or take it's constant ambiguous meaning between languages of assignment and/or equality testing. And this isn't even delving into the black arts of defining types, where the really ugly punctuation toolkits get opened. I don't care whether or not they represent regular functions nor what their calling syntax is. What I care is that the base language has many many dozens of them to remember and then to parse in the wild, and then that authors are encouraged to continue proliferating more of them: ```Haskell -- What does this 'mouse operator' mean? :thinking_suicide: (~@@^>) :: Functor f => (a -> b) -> (a -> c -> d) -> (b -> f c) -> a -> f d ``` Credit: Kowainik's Haskell Style Guide https://kowainik.github.io/posts/2019-02-06-style-guide https://kowainik.github.io/posts/2019-02-06-style-guide
- smegma2 1y agoAgreed, I think this tutorial is good: https://hackage.haskell.org/package/lens-tutorial-1.0.5/docs/Control-Lens-Tutorial.html https://hackage.haskell.org/package/lens-tutorial-1.0.5/docs...
- kccqzy 1y agoMy biggest piece of advice for people using lenses is to ditch all the operators. Things like ^. or ^.. or ^? or ^@.. or even <<|>~ are all real operators. Yet they look like line noise. Nobody fully remembers them anyways. Just ditch all operators. Use named functions. The function toListOf is immediately clear what it's doing (that it takes a structure and a fold to convert to a list) but ^.. is not. In general I avoid all custom operators and only use operators that are in packages preinstalled by the compiler (basically just base and containers).
- kqr 1y agoI agree strongly with this and take it one step further: I avoid the infix backticks that turn functions `into` operators. But I'm not a hardliner. I do use backticks sometimes when building joins with Esqueleto and I do use a limited set of lens operators, like ^. and sometimes the %= variants if the situation calls for it.
- amelius 1y agoMaybe a text-editor should allow the user to look at source code through different "lenses" (pun intended) and show the meanings of symbols whenever the user wants to see them.
- ashton314 1y agoEmacs (of course) has `prettify-symbols-mode` which lets you describe symbols (eg lambda) and replacement characters (eg λ); the effect is purely in the display system—the underlying buffer does not get modified.
- chowells 1y agoI strongly recommend using the lens operators. They are uniformly named such that you can trivially identify their behavior based on their lexical construction, and using them reduces mental parsing overhead significantly. For the former assertion: ^. means "get a single result". ^.. means "get multiple results". ^? means "get zero or one result". ^@.. means "get multiple results, along with their indices". <<|>~ means "modify a value by combining the target with the |> operator from Snoc, then return a tuple of the old target value and the full structure including the combined value". There is a tiny language in the pattern of operator names, and it's worth the 3 minutes of work it takes to learn it. And as a reward for learning it, you get to write expressions with far fewer parentheses. This is a massive win. Parenthesized expressions introduce a miserable minigame during reading, where you have to properly match each paren to its correct partner keeping a mental stack to handle nesting. By contrast, the lens operators give you the far simpler mental parsing task of separating the optic, the input, and the operation on the input. There's no nesting involved. The process is a simple visual scan that doesn't require keeping a mental stack. It's a lot easier to quickly read and comprehend. About the only thing you lose is the ability to easily read code out loud. I don't limit myself to thinking in sounds, but I guess for some people it's important to communicate code out loud. For those kinds of pedagogical purposes, I guess it's ok to pass on the operators. But for code I'm going to work with over a long period of time I'd much rather have the readability advantages of the operators.
- haskman 1y agoIf you are looking for a more accessible introduction to lenses, this guide to optics in PureScript is great (and PureScript is basically Haskell). https://thomashoneyman.com/articles/practical-profunctor-lenses-optics/ https://thomashoneyman.com/articles/practical-profunctor-len...
- eigenspace 1y agoJulia actually has a very nice implementation of lenses in the Accessors.jl package: https://juliaobjects.github.io/Accessors.jl/dev/ https://juliaobjects.github.io/Accessors.jl/dev/ I find it to be a lot more comprehensible and transparent than the Haskell version.
- rrgok 1y agoI don't understand why Haskell can't provide an imperative interface (at the grammar level, not semantic level) to get/set values in a type. If you can provide the do-notation to "simulate" imperative code, then why not?
- ethan_smith 1y agoHaskell's design prioritizes referential transparency and equational reasoning, which would be compromised by imperative get/set operations that mutate state directly - lenses provide a purely functional alternative that maintains these properties.
- rrgok 1y agoThat’s why I said at the grammar level and not at semantic level. I also brought the do-notation example, which kinda gives an imperative interface to the various monads
- tome 1y agoYou get that on top of do notation, with no additional syntax required for example `IORef` or Bluefin's `State`: https://www.stackage.org/haddock/lts-23.27/base-4.19.2.0/Data-IORef.html https://www.stackage.org/haddock/lts-23.27/base-4.19.2.0/Dat... https://hackage-content.haskell.org/package/bluefin-0.0.16.0/docs/Bluefin-State.html https://hackage-content.haskell.org/package/bluefin-0.0.16.0...
- johnfn 1y agoEveryone is like "Haskell is such a cool language, it's so much more clear concise and understandable than that stupid language you like so much" (their words, not mine). Then you ask them how they write `foo.bar.baz = 1` and you get 50k words of documentation, 113 new operators[1] like `<<<>~`, and a library with 20 new dependencies. I make fun of them only because I love them - I think Haskell has brought us a lot of cool things like Maybe and Either - but how has no one ever taken a step back and gone "wow, this seems a tad complex for what we're trying to accomplish"? [1]: I'm not even exaggerating - https://hackage-content.haskell.org/package/lens-5.3.5/docs/Control-Lens-Operators.html https://hackage-content.haskell.org/package/lens-5.3.5/docs/...
- fud101 1y agoI just want one good monad tutorial that doesn't mention haskell. Just one.
- upghost 1y agoMonads are a set of annotated functions or methods that participate in shared encapsulating middleware. It's kind of like writing an interpreter for existing code by changing shape of the inputs, outputs, and possibly even flow control of the execution of those functions -- but without writing an interpreter. The easiest example would be something like wrapping a bunch of arithmetic operations with a "cumulative" monad. Effectively this changes your add, sub, mul, div functions such that instead of taking 2 floats and returning a float, they take a hashmap and return a hashmap. The hashmap consists of the original args as well as the cumulative total, for whatever reason. The details of the hashmap are hidden from you, you use the functions as per normal. You could also make the wrapper monad have some state, and then batch the operations while making them appear to execute sequentially, or make it appear you are doing pure logic when I/O is happening under the hood. While you can do monads in dynamic languages, it can be hard to reason about changes to the code without strong compiler support, so typically you see it more often implemented in statically typed languages. In dynamic languages such as lisp you might be better off writing a small interpreter, and in OO languages there are other patterns that might serve the purpose better. I still don't know what a monoid is though. Or an applicative.
- srik 1y agoI learned lenses from the mentioned Edward Kmett video but wish I'd learned from the "Optics by Example" book instead; it's more cohesive, comprehensive and can save you a bunch of time - https://leanpub.com/optics-by-example/ https://leanpub.com/optics-by-example/
- 0_gravitas 1y agoIf you're in the Clojure world and feel an appetite for something like Optics, checkout the Specter library from RedPlanetLabs/Nathan Marz; it's Optics by another name, but functionally/philosophically quite similar. https://github.com/redplanetlabs/specter https://github.com/redplanetlabs/specter