3 ms·
"You can write both styles of program in both languages" No you can't, not in any way that's practical. It's possible to write Haskell by wrapping every value
by weavejester 9y ago
"You can write both styles of program in both languages"
No you can't, not in any way that's practical.
It's possible to write Haskell by wrapping every value in a Dynamic type, but possible does not mean feasible.
If you don't believe there's a distinction, then try writing a functionally equivalent `assoc-in` in Haskell. I don't mean sketch out a design in pseudo-code; I mean produce a fully working function that operates seamlessly with all possible types of Data.Map.
"So, you’ve shown that assoc-in can be written so long as type guarantees are thrown away. That seems like a reasonable reason to pick lenses either way."
Well, that's the question: is it?.
Lenses can be typed, but `assoc-in` is conceptually simpler. Haskell advocates using only solutions that can be typed; Clojure advocates using the simplest solution.
Static typing is a constraint, because it limits the solutions that are feasible and idiomatic. In return it provides a compile-time guarantee. The question is whether the guarantee is worth the solutions that are (for all practical purposes) removed.
Immutability is another type of constraint. As is automatic memory management, variable scoping... programming languages are designed around constraints. Pretending that you can introduce a constraint and not narrow the solution space is wishful thinking.
- tel 9y agoIt’s feasible and easy to write assoc-in atop of Dynamic... it’s just not done because nobody programming in Haskell thinks it’s valuable. We could choose to support much more opt-out dynamic behavior no sweat, but nobody wants to. The idea of assoc-in working for every type of Map also doesn’t make sense. Map only exists statically. Types as Clojure discusses them exist at runtime, are statically Dynamic, and it’s trivial to write assoc-in that works over all of them in any language. Your argument hinges on the idea that it’s impractical to write using Dynamic in Haskell. I do not think this is true. There is perhaps some value in greater library support, but it is easy to do this. It is simply not considered valuable.
- weavejester 9y ago"It’s feasible and easy to write assoc-in atop of Dynamic..." Then why don't you do it and post up the code? If it's as easy as writing the same function in a dynamically typed language it shouldn't take more than a minute or two. "The idea of assoc-in working for every type of Map also doesn’t make sense. Map only exists statically." Maybe you're misunderstanding me? I mean it should work for every `Data.Map k a`, where `k => Ord`, just like all the other Data.Map functions. "Your argument hinges on the idea that it’s impractical to write using Dynamic in Haskell. I do not think this is true." Then try it?
- tel 9y ago> I mean it should work for every `Data.Map k a`, where `k => Ord`, just like all the other Data.Map functions. This is where we're got a difference of opinion. My statement is that assoc-in doesn't do anything close to working over "every `Data.Map k a`". Data.Map is a compile-time idea classifying names in the language and the Data.Map functions are designed to respect that both dynamically (manipulate some memory properly) and statically (create updated contexts with new and different information). On the other hand, assoc-in works only dynamically/at runtime over all kinds of (Clojure and Java) data. In particular, it has meaningful semantics for every possible input value although it only has "interesting" semantics for certain runtime shapes. That's easy to write in Haskell. https://gist.github.com/tel/bb84fcc3f1b7488b53349156284b509a https://gist.github.com/tel/bb84fcc3f1b7488b53349156284b509a
- weavejester 9y agoYour code doesn't compile. I can fix the obvious typos and missing imports and language pragma, but the type errors that remain are beyond my knowledge to correct.
- tel 9y agoApologies, quick sketch in an airport between flights. May fix this later when I’ve actually got an internet connection.
- tel 9y agoI fixed the type errors in what I presented before. Little changed: I had to fix the typos, bad imports, and missing pragmas, and then I had to instantiate Val as Hashable and Eq, but since all things inside of Val are Hashable and Eq it was straightforward. https://gist.github.com/tel/bb84fcc3f1b7488b53349156284b509a https://gist.github.com/tel/bb84fcc3f1b7488b53349156284b509a
- weavejester 9y agoCan you give an example of use? It's not clear to me how this interacts with standard Haskell data structures. If I have an existing map, do I need to walk the tree and encase everything in a `Val`, and vice versa when I want to pull values out?