5 ms·
Purely functional introduces lots of issues on it's own. (Look at all the monad insanity Haskell has to do to get the equivalent of a print statement).
by TylerE 3y ago
Purely functional introduces lots of issues on it's own. (Look at all the monad insanity Haskell has to do to get the equivalent of a print statement).
- docandrew 3y agoI thought the D language had a really nice take on this with its notion of “weak” purity, allowing for straightforward allocations and I/O: https://klickverbot.at/blog/2012/05/purity-in-d/ https://klickverbot.at/blog/2012/05/purity-in-d/ I think the idea is that if a function always gives the same result with the same inputs, it is considered “pure enough.”
- tome 3y agoIt's very hard to do that if you want to use higher-order functions ergonomically. In fact that's the entire reason this area of language design is difficult at all. Specifically, if you define a higher order function (e.g. `f :: (a -> b) -> c` in Haskell notation) and you want to specify that it is "pure" if and only if its argument is "pure". How do you do that in D? I bet you can't!
- the-smug-one 3y agoWhat's insane about monads :-)?
- javcasas 3y agoHe doesn't understand them, therefore monads are insane.
- TylerE 3y agoI understand them just fine. The juice ain’t worth the squeeze, and I don’t appreciate the personal insult
- master-lincoln 3y agoI could not see any insults in this thread
- tome 3y agoAlthough I disagree with TylerE about the issue that started this thread, I agree that assuming that someone doesn't understand something is generally considered rude and would advise people against that. I would doubly advise them against it if they are from the Haskell community, because it is one way our community could get a poor reputation. Instead I hope we can be welcoming and tolerant, even of people who may not understand things, in the hope that they will come to understand them through interacting with us, or at the very least enjoy the experience.
- master-lincoln 3y ago> I agree that assuming that someone doesn't understand something is generally considered rude. I think assuming that someone doesn't understand something is only rude if there are no indicators for a misunderstanding. javcasas seemed to assume that TylerE doesn't understand Monads because TylerE stated that there is a Monad insanity in Haskell to replicate a print statement. I would also assume javcasas' comment wasn't made in good faith, but I still don't see that an insult was voiced. Not every rudeness can be interpreted as an insult I think
- tome 3y agoI think you're splitting hairs! Equivocation about what's rude and what's not is not a good look for the Haskell community.
- javcasas 3y agoYou understand the data structure. Probably the chaining rule, even probably the monoid in the category of endofunctors. What you don't understand is the existence of it. Monads is a solution for dealing with IO in a strongly typed programming language, where we want all functions to be pure, and we don't have access to linear types. (almost) Every other programming language, when it had the chance at doing this, just threw the towel without a fight, and decided to allow IO everywhere. Haskell decided to stick to its principles instead, and produced something different, guided by a different set of constraints. Different means with different tradeoffs in different places. If Haskell instead decided to allow mutability everywhere, like most programming languages, we wouldn't be talking about it. Because it would be another language with weird syntax, and you can find a lot of them in the list of defunct programming languages at wikipedia. And the juice is worth the squeeze if you want to see breakthrough things in programming, and not just another Algol with updated syntax. For reference, other samples of groundbreaking (to some degree) stuff: * Rust: mutability only when the borrow checker allows it * Coroutines/continuations: functions that depart away from the entry/exit model * Prolog: a programming language constructed around functions with 4 connection points: enter/exit/fail/redo
- aranchelk 3y agomain = putStrLn "foo" Truly insane.
- TylerE 3y agoCome on, that's not in good faith and you know it. That's a special case. Now do it inside a vanilla function that isn't implicitly run inside the IO monad.
- aranchelk 3y agoWhat do you mean by vanilla? A function that doesn’t have a monadic return value? What do you mean by run implicitly? I explicitly put IO expressions in the main function and they run. That’s the same as any imperative language. I’m trying to figure out what you’re getting at. Are you saying it’s hard to do IO outside of the IO Monad?
- tome 3y agoOne might say your original claim was not in good faith. You said > Look at all the monad insanity Haskell has to do to get the equivalent of a print statement but it's easy to do that! If you meant something more complex and subtle perhaps you should have made a more complex and subtle claim.
- TylerE 3y agoyea, it's so easy that's why there's dozens of many-page tutorials on the topic.
- Twisol 3y agoYou don't need to understand monads to do IO. From [0]: > There is nothing that has to do with monads at all in printing a string. The idea that `putStrLn "hello world"` is monadic is as absurd as saying that `[1,2,3]` is monadic. You haven't linked any exemplar tutorials, but I feel confident in saying the ones you're referring to teach the general concept of monads, and not how to do IO with monads. Quite a number of JavaScript developers learned how to use `andThen` with Promises/A+ back in the day, and they didn't need to learn about monads either. (In fact, when it was raised that promises are really monads, there was serious drama and outrage [1] -- an existence proof if there ever was one, that you can use something productively without understanding it as a monad.) Likewise, nobody would claim that you need to understand monoids before you can concatenate lists. Concatenating lists is as native to lists as sequencing commands is to IO; it's just part of how those types work. The monad interface abstracts over that idea, and learning that abstraction in its full generality is, typically, what people stumble on. [0]: https://blog.jle.im/entry/io-monad-considered-harmful.html https://blog.jle.im/entry/io-monad-considered-harmful.html [1]: https://github.com/promises-aplus/promises-spec/issues/94 https://github.com/promises-aplus/promises-spec/issues/94
- tikhonj 3y agoIt's no more insane than async programming. In fact, it's less insane: it's what you'd get if you let async and await be first-class citizens in your language instead of awkward special cases.
- MrBuddyCasino 3y ago> It's no more insane than async programming. That’s damning with faint praise.
- mikhailfranco 3y agoErlang/Elixir are async by default. Non-blocking non-erroring send ! and optionally blocking/non-blocking receive, with pattern matching, are built in to the language. Not a monad in sight.
- mrkeen 3y agoI looked. main = putStrLn "Hello, world"
- TylerE 3y agoYou didn’t look very hard. Main is very special in Haskell.
- tome 3y agoIn what way is it very special? Is it more special than `main` in C, for example?
- TylerE 3y agoYes. It runs inside the IO monad.
- coldtea 3y agoYeah, so? If it's not main you just need to mark your function as being of IO () type. Or e.g. IO Integer if you also return an integer, and so on. There is 5x as much ceremony for simple stuff in C or Java...
- riffraff 3y agoI am no Haskell buff, but I believe the common complaint is that "just need to mark your function as IO ()" has non-local effects, you end up needing to propagate a bunch of extra stuff everywhere. AFAIU the Haskell community recognized the issue as common enough to grant the existence of Debug.Trace.
- mrkeen 3y ago> you end up needing to propagate a bunch of extra stuff everywhere. Declaring a function as non-IO is a contract to your callers that you don't do IO. You don't need to do it. You can write everything in IO if you choose. You can also call into the wonderful ecosystem of libraries, because IO functions can call other IO functions, as well as non-IO functions. There is only ever friction if you declare your function to be IO-free. If you declare your function to be IO-free, but call IO from inside it, it's a compile error because of course it is. So why bother declaring anything IO-free? If you do arbitrary IO in a Parser, you can't back-track. If you do arbitrary IO in Parallel code, you invite race conditions. Transactions is my favourite example, though: .NET [1] > Disillusionment Part I: the I/O Problem > It wasn’t long before we realized another sizeable, and more fundamental, challenge with unbounded transactions [...] What do we do with atomic blocks that do not simply consist of pure memory reads and writes? (In other words, the majority of blocks of code written today.) This was not just a pesky question of how to compile a piece of code, but rather struck right at the heart of the TM model. Scala: [2] > ScalaSTM does not have the goal of running arbitrary existing code, which is where most of their problems arose. Java/Akka: [3] > STM is considered as a failed experiment Clojure: [4] > Very simply the side-effects will happen again. In the above case this probably doesn’t matter, the log will be inconsistent but the real source of data (the ref) will be correct. Sorry for the rant, but I really needed to highlight the fact that nonIO-calling-IO is not some language design flaw created by out-of-touch academics. It's a fundamental problem. [1] https://joeduffyblog.com/2010/01/03/a-brief-retrospective-on-transactional-memory/ https://joeduffyblog.com/2010/01/03/a-brief-retrospective-on... [2] https://nbronson.github.io/scala-stm/faq.html https://nbronson.github.io/scala-stm/faq.html [3] https://groups.google.com/g/akka-user/c/3JWz-X5dbe8/m/YiV4WFG0qh0J https://groups.google.com/g/akka-user/c/3JWz-X5dbe8/m/YiV4WF... [4] https://sw1nn.com/blog/2012/04/11/clojure-stm-what-why-how/ https://sw1nn.com/blog/2012/04/11/clojure-stm-what-why-how/
- mjan22640 3y ago1. You dont need a monad to do io in Haskell, you can do that directly. 2. Monad is a tool that offers a "grip" over io, ie your code still yields easily to formal proofs despite using io for example. 3. The sanity and insanity of controlled and uncontrolled io is imho the exact oposite of what you seem to imply.
- coldtea 3y agoYes. So insane /s myMethod :: IO () myMethod = putStrLn "Hello World!"
- akhosravian 3y agoNot the OP but I’m guessing the problem they are referring to is when people think they need to understand what a monad is from a category theory pov before they can write meaningful code. Or worse yet, when they are trying to teach the language to others and think they need to explain that in order when a newcomer just wants to print a string. It’s like a built in bikeshedding bait for the whole programming language.
- tome 3y ago> people think they need to understand what a monad is from a category theory pov before they can write meaningful code Yes, this is a very strange belief