27 ms·
Are Monads a Waste of Time?
- Legogris 9y agoSomewhat tangential, but I became infatuated with Idris's Effect system as a more approachable alternative to using monads directly. Yes, it's still monads under the hood IIRC, but the syntax is a lot easier to reason about IMO. https://www.idris-lang.org/documentation/effects/ https://www.idris-lang.org/documentation/effects/
- tombert 9y agoI feel like a recurring theme I find in Idris (though keep in mind it's just something I play with every now and then, not something I use with any kind of regularity) is that it has this "feels like Haskell, but less frustrating and cleaner" quality. I feel like I make less dumb mistakes while using it, and it gives me pretty much all the stuff I love about Haskell. You of course have the relatively simple effects system (as mentioned),, but you also have the ability to use `do` notation without being in the monad context, and eager evaluation, which I find makes my program simpler to reason about.
- Legogris 9y agoI agree. I like to think that Idris is to Haskell what C# is to Java, with the exception that it's still a non-production-ready academic open source language.
- lmm 9y agoIt's not that academic AIUI - it was designed for production use, right?
- Legogris 9y agoFrom the release notes of 1.0[0] last year: > Idris is primarily a research tool, arising from research into software development with dependent types which aims to make theorem proving and software verification accessible and practical for software developers in general. In calling this “1.0”, we mean no more than that the core language and base libraries are stable, and that you can expect any code that compiles with version 1.0 to compile with any version 1.x. > Since Idris has less than one person working on it full time, we don’t promise “production readiness”, in that there is still a lot to do to make the compiler and run time efficient, and there may be libraries you need which are not available. And, there will certainly be bugs! [0] https://www.idris-lang.org/idris-1-0-released/ https://www.idris-lang.org/idris-1-0-released/
- empath75 9y agoAren’t the state like effects limited to the scope of that block?
- olavk 9y agoNo, but the state is part of the type signature, so the scope is explicit.
- _pmf_ 9y ago> Are Monads a Waste of Time? No, they are not supposed to have side effects.
- tonyedgecombe 9y agoVery funny. Although like most humour, somewhat wasted here.
- placebo 9y agoI think at the right dosage, it's welcome. For me, mild doses of good humour upgrade the most serious of discussions without detracting from their professionalism.
- carlmr 9y agoAgreed, let's not become robot news.
- andrewflnr 9y agoI've gotten loooots of upvotes from basically joke comments. HN doesn't like all humor, but if it's actually clever, it'll work.
- always_good 9y agoHumor does fine on HN. Just be wary of conveniently blaming the community when your jokes flop. ;)
- deleted 9y ago[deleted]
- dmitriid 9y agoTh author asks a general question, using JS code as an example of imperative code because it's faster to write and the syntax is familiar to many programmers. The second top comment starts with: > JavaScript is a mess with its truthiness, implicit conversions, dubious semicolon insertion, second class references, automatic variable declarations, weird scoping, etc.. You'd need to try harder to make the Haskell imperative monad just as bad as JavaScript. That is not the point, is it? Thankfully most other comments discuss the actual question asked, not the pet peeves aimed at a particular language.
- js8 9y agoI think no, and why can be found in these articles: http://degoes.net/articles/modern-fp http://degoes.net/articles/modern-fp http://degoes.net/articles/modern-fp-part-2 http://degoes.net/articles/modern-fp-part-2
- platz 9y agoThose posts by Degoes are more polemical than techniques that he actually uses in production.
- olavk 9y agoMonads make a lot of sense in a pure functional language like Haskell, because it allows you to program in an imperative style when you need it, and keep the rest of the program pure and functional. The benefit of State and IO monads is not that you can use them everywhere so you now have an imperative language. The benefit is you can explicitly delimit their use, and you still get the "easier to reason about" for the rest of the code. For languages which already supports mutable state everywhere by default it does not make much sense to use monads for this.
- paulddraper 9y agoAgreed. The "islands of immutability" approach.
- willtim 9y agoI agree, but Monads also simplify non-blocking concurrent programming, allowing users to think sequentially, see F# Async and Haskell IO. C# had to add Async/Await support in the compiler and I would argue it is not as pleasant as the F# version using Monads.
- seliopou 9y agoThe separation of pure and impure code in Haskell isn't something inherent to monads but is instead a side-effect (hah) of the typing rules of the language. It's easy to see how this separation need not hold when using monads (look at any monad library in virtually any other language), but more importantly there are ways to accomplish this separation without the use of monads (an effect-tracking type system is being developed along side OCaml's algebraic effects/multicore project).
- aaron-lebo 9y agoDoes it make sense to view IO/State monads in Haskell as analogous to unsafe blocks in Rust?
- quchen 9y agoI don’t think so. - IO can be seen as a tag added to a type that brings »the outside« into scope: the console, the network, current time, the harddrive. In Rust, these are always available, regardless of the type of the expression at hand. - IO is »viral«, in the way that things that touch IO will become IO as well; there is no way to remove IO to yield a pure value. If a function in Rust contains an unsafe block, is the whole thing unsafe? I don’t know enough Rust, but I think it’s not.
- pka 9y agoJust to point out the probably obvious thing: that's only one type of monad (the state monad). There are many other things which form a monad and can't be represented easily in JS or other imperative languages. Even though even the state monad is a clear win in my opinion (since it explicitly delimits a stateful computation which can then be embedded in a pure one in a principled way), the concept itself is much broader and thus much more useful than just allowing for imperative syntax in a pure language. For example, the continuation monad, which is just a library in Haskell, can't be implemented in most imperative languages without extending the language itself (async in JS, C#, etc).
- jerf 9y agoTo emphasize, of course the monad interface isn't useful if the only implementation of it that you use is also the monadic implementation used by an imperative language. But if you "just" use an imperative language, you lose all the other implementations because the language hardwires the "conventional" one at the bottom. You lose the parser implementation of the monad interface, the free monad implementations (which are useful for writing "programs" that are then separated from their interpreter), the software transactional memory implementation, the probability implementation, the effects-controlling implementations (that go beyond "either in IO or not" to implement more granular controls), and the many other things that have been implemented. Obviously that's ultimately a viable solution since almost every programming language works that way. But if you're going to ask "is the ability to implement the monad interface worth it for some given language?", you aren't going to get anywhere if you consider only one of the many implementations of the interface. Why would anybody use the iterable interface if all it could do is the equivalent of "for (i = 0; i < arr.len; i++)" and couldn't iterate over a binary tree or hash table as well? Why would anyone use any interface if an interface only has one implementation, ever? The problem lies in the question, not the value of the interface. (I'm trying to get better at phrasing my posts about "monads" better because one of the major problems they have is that people think of "monad" as a noun. But it is an interface, just like in Java or a Rust trait, that can be implemented by a type; it just so happens that the interface is not something that can be cleanly represented in most statically typed languages because of the high-order polymorphism. "Monad" is an adjective, not a noun. And "monads" aren't "about managing state" any more than the Iterable interface is about "incrementing an integer to walk over an array"; the conceptual error is the exact same kind in both cases.)
- tome 9y agoMonads cannot be a waste of time. Monads just are. It can be a waste of time to design an effect system for Haskell around monads (it's probably not) or it can be a waste of time to design an effect system for Javascript around monads (it might well be). But monads cannot be a waste of time.
- 3minus1 9y agoYour comment is really pedantic. Obviously the concern is whether using monads is a waste. If I say "television is a waste of time" are you also going to correct me that tvs just are?
- tome 9y agoBy no means. There's this idea floating around that monads are things that had to be "introduced" into Haskell to "solve" certain problems with purity. This idea is false. Furthermore this question misses half the point of monads, that is, that you can program generically over them. Sure, that one example makes the IO monad look just like code in any other imperative language. But I can also use do notation and monad combinators with lists, coroutines, promises, futures, ASTs, and indeed any other monad I care to come up with. It may seem that any individual monad qua monad is a waste of time but when taken in totality it is a completely different question. Since the question mentioned no other monad than IO it doesn't begin to address the important issues.
- danharaj 9y agoThe much less discussed killer app of monads is monad transformers, which add a new dimension of program architecture to the toolbox.
- KirinDave 9y agoI agree, although it's funny because the community has been trying to come up with replacements for mtl for some time now.
- nabla9 9y agoAs others have said, there are many different kinds of monads. In my mind, for practical reasons, uniqueness typing >> state monad. Uniqueness typing allows programmer to use stateful programming locally while developing strictly functional programs in at scale. Best of the both worlds.
- thanatropism 9y agoMonads are just monoids in the category of endofunctors. Don't complicate that too much!
- bunderbunder 9y agoI've been wondering a similar thing, lately. In principle, I like the way that Haskell enforces purity at the compiler level, and kicks everything impure out to the boundary of the program. I can try to write code that's that clean in another language, but it's always an unstable equilibrium. The compiler won't help me make sure functions stay pure, so all it takes is adding one little bit of statefulness to one function out there, and suddenly, like a virus, everything that calls it, everything that calls anything that calls it, and so on is impure, too. On the other hand, monads are *@#$% opaque. I can't help feeling that, for many use cases, they are unnecessarily opaque. At the risk of being branded a heretic, not all assignment makes a function impure. If the function never modifies or uses a mutable variable that's visible outside its scope, while it's visible outside its scope (e.g, it's fine to return that accumulator when you're done with it), and it's more efficient (either in terms of performance or code clarity) to get the job done with some mutation, why not? I'd like a language that doesn't worry so much about what consenting adults do behind closed doors. Rather than not letting me do it at all, I'd rather a language that just helps me make sure I'm doing it in a safe manner that doesn't lead to viral impurity.
- aweinstock 9y ago> not all assignment makes a function impure That's exactly what the ST monad/STRef's are for. {new,read,write}STRef let you manipulate mutable references while keeping track of their scope in the type of the reference. runST encapsulates a chunk of code that manipulates mutable variables in an externally-pure way into a pure function. The "Lazy Functional State Threads"[1] paper on it is a pretty good read. [1]: https://www.microsoft.com/en-us/research/wp-content/uploads/1994/06/lazy-functional-state-threads.pdf https://www.microsoft.com/en-us/research/wp-content/uploads/...
- lmm 9y ago> The question is, just looking at the above code, it looks like "s" is mutated. Yes the implementation in the monad could be pure and use state threading, but how does that help us reason about the above imperative program? The value of the monad is precisely that both these things are true. We can use our fast-and-loose imperative intuition most of the time, but if we ever get confused about how the "mutation" of s interacts with some other effect (e.g. a continuation), we can desugar the code into the pure state-threading version and bring all the power of our pure, referentially transparent reasoning tools to bear. Most of the time we don't, because that version of the code looks a lot more cumbersome, but it's there if we need it. Whereas if we find ourselves in the same position with the Javascript, we're stuffed; when the effect interactions get too complicated to reason about imperatively, we have no alternative.
- Waterluvian 9y agoI stumbled through high school math and never took any in university so this is all wizardry to me. All I know is that when I began using immutable data in JavaScript, my data processing workflows and state machines became nearly trivial to understand and debug. Pure functions are also beautiful to reason about and test and debug. I'm not sure about monads. I barely understand them. But if I could have one wish, it would be to make immutable data structures first class in more languages, like JS and Python.
- gmfawcett 9y agoYour intuition about the benefits of pure functions & immutability are spot-on, and I think that any proponent of monads would agree that these are fundamentally more important concepts than monads themselves. (Many of the ways that people use monads would break, or lose their point, if the data they operated over could be mutated outside of the monadic context.) You can get an awfully long way with immutable data structures without involving monads. There are plenty of languages that give priority to immutable data, but don't have monads in any inherent way: Prolog, Erlang, Ocaml, and Scheme (to a slightly lesser extent) all come to mind.
- zmonx 9y agoProlog has definite clause grammars (DCGs), which are very similar to monads. You can think of a DCG as giving you two implicit arguments, which you can use to express concatenations and in fact arbitrary relations between states. There are also ways to access these implicit arguments, which are similar to the corresponding constructs in Haskell. DCGs are a very important feature of Prolog. They are frequently used for parsing and state transformation tasks. Like monads in Haskell, DCGs often make working with immutable data much more convenient, because you can make the more uninteresting parts of your code implicit. Other logic programming languages like Mercury also support DCGs.
- gmfawcett 9y agoIt never occurred to me that there were similarities between DCGs and monads, but that's an interesting argument. Thank you for this!
- brudgers 9y agof = let s1 = 23 in let s2 = 42 in s2 Grammatically, this reminded me of Erlang. Hence, then indirectly of Prolog. And now that I think about it, Prolog is considered a logic programming language. I'm not advocating logic programming lanaguages, but it seems that it might stand to reason that the features of logic programming languages facilitate reasoning about programs written in them. Looping back, Erlang doesn't generate discussions about monads. Erlang is engineered so programmers don't think about monads. Erlang programmers just use them. It's transparent. It's non-controversial because Erlang doesn't stake out an intellectual argument.
- macintux 9y agoWhen I worked at Basho, the senior Erlang developers definitely thought/talked about monads and how useful they could be in certain situations. (I, alas, was and remain insufficiently clueful about monads to understand the discussions.)
- mwkaufma 9y agoErlang is pure, but it's not lazy, so it's not an issue like in Haskell.
- brudgers 9y agoI'm not sure there is anything lazier than "Let it crash." Erlang is lazy at the question in addition to being lazy at the answer. However, all that laziness is transparent because Erlang is an engineering artifact not an academic artifact.
- barrkel 9y agoYou're using monads whenever you use Java 8 streams, Javascript promises, ActiveRecord and collection operations in Rails / Ruby; monads are everywhere these days. Monads are one of the handiest design patterns you can use; all you really need is a decent lambda syntax and you're off to the races.
- skybrian 9y agoThe monad abstraction takes a lot of unlike programming features and abstracts away most of the important stuff to show something they have in common. The question is whether users of those features need to know about this abstraction? Why should we care that they have something in common? They're mostly different. As concepts get more abstract, they get harder to teach. I don't think knowing that JavaScript promises are a monad is all that helpful when learning to do async I/O.
- the_af 9y ago> Why should we care that they have something in common? They're mostly different. You can of course ignore it, but it's useful to care about this because they are actually similar over this shared commonality. You start seeing patterns over which you can apply the same general functions. Just like you can map over an Option or a List or any "mappable-over" structure. This is similar to asking (in a made up language, forget the specifics): "why should I care that Lists and Sets and Arrays and Enumerations have a shared 'iterable' interpretation? Sets and Lists are mostly different!" Well, because sometimes it's useful to have functions that operate on iterables, instead of writing one for Lists and another for Sets. Once this idea "clicks" in your mind, you start seeing more and more of this commonalities, and it starts to shape how you think about coding.
- skybrian 9y agoSure, I agree. My point is that just as with other design patterns, it's possible to overdo it and lose your audience. Enthusiasts can definitely go overboard here.
- 9y ago
- sfilargi 9y agoThe problem here is not the Monad, but the “do” notation. Rewrite your code without it, and will be more clear and less “waste of time”
- azinman2 9y agoCan someone please explain in a simple way what Monads are and why I want to use them in normal daily programming (assume, incorrectly, that I only know Python)? I know I can google this, and have, and unfortunately I came away even more confused as a non-Haskell practitioner.
- AlexCoventry 9y agoIn computer science, a monad is a notation representing an intermediate value and its computational context. E.g., data necessary to continue the next steps of a calculation, or some kind of marker of the value's source (IO monad.) It's an abstraction which rarely carries its own weight, but it's necessary to understand Haskell for what seem to amount to cultural reasons. Other strongly typed functional languages don't place nearly so much emphasis on it.
- roflc0ptic 9y agoThe definition of the thing we call “monads” is a poor place to start understanding what they’re for. The only way to understand monads is to use a number of monads, and you’ll start to see why they’re useful. One great monad is the Option monad. It lets you represent, at the type level, the two casss of having something or not having. Think about when you use a python query operation that may return nothing. You don’t know if you’ll get back an empty list, or a null, or what. If the API returned an option, this would indicate what happens when you get nothing back. That’s cool. You can then do computations against maybe having a value. Option.map(lambda) will apply that lambda function to the value only if it exists, saving your program from blowing up on a null. Even better, tho, you can chain a bunch of operations that may fail together. In the map example, ifyour lambda also returns an option, you would end up with the type Option[Option[A]]. Monads implement a flatten method that will turn an Option[Option[A]] into an Option[A]. They abbreviate this with “flatMap”, which can be implemented as a call to map, followed by a call to flatten. Futures are another great monad that help model asynchronous operations. Val f = Future(mydatabasequery) will return a Future[A], read as “future of type A”. You can perform computations on the result using the map function: f.map(lambda). You don’t know when this will happen, you just know it will. If your lambda also returns a Future, you will end up with Future[Future[A]]. You convert this into a Future[A] with the Future.flatten function. The shorthand for this is.flatMap(lambda). Another great monad is the Either[A, B] monad. It’s like the Option monad, but rather than having None or Something, you have Left or Right. If you have an operation that may throw an exception, you can wrap it in an Either. A left value will be some error, and the right value will be success. You can conditionally perform operations on the success using the Map function: Either.map(lambda). If the Either doesn’t have a Right value, it will not execute your lambda, saving you from performing an incoherent operation. In python sometimes you might return either a string or an int, representing failure or success. Either[String, Int] is just formalizing that pattern, and letting your compiler prove that you’ve handled both cases. You can model sequential computations that may fail using either: if your lambda returns an either, you’ll get an either[string, either[string, int]]. You can flatten these using the Either.flatten method. The shorthand for this would be flatMap.
- bitL 9y agoFunctional programming has the following issues: - it tries to abstract away von Neumann architecture and make it more math-like, stateless, true and permanent. Yet von Neumann is completely stateful (resembling real-world in its complexity and model approach), causing all kinds of frictions, for which monads and other syntactic sugar were invented - while Turing complete, it has some weird properties, making it difficult or inefficient to change communication between various components that are using deep function calls when such a need arises in the future. This leads to using mutable "shortcuts" that render a lot of advantages functional programming might have had useless and starts resembling imperative/OOP programming with its issues again - trivial things like IO can't be modeled without side-effects, so any software requiring input from keyboard, loading external files etc. can't be pure - often functional constructs make code unreadable despite readability being one of the main reasons for its existence - bottom-up creation of algorithms is preferred by many language authors, making it difficult for beginners - if you really want to know how it works, it takes 5+ years PhD level of studies in abstract math Disclaimer: I approach 100 languages I've used in production, worked for companies that created some of the most popular languages and hate them all ;-) I hope to work on AI-assisted language creation in the near future.
- KirinDave 9y agoHello, most of your points seem wrong in the extreme and I feel like addressing them. I confess I pressed the enter key hard a few times as I wrote this, gritting my teeth at some of your points. But I have tried to keep a level tone to help people see that many of these points either are simply FUD or, in a few cases, haven't been true for well over a decade. But, first and foremost, it's very clear you've conflated Haskell (and perhaps Purescript?) with all functional programming. This is a mistake, and many functional languages do not make use of pure functions, laziness, monads, or algebraic data types. > - it tries to abstract away von Neumann architecture and make it more math-like, stateless, true and permanent. Yet von Neumann is completely stateful (resembling real-world in its complexity and model approach), Most languages abstract away von Neumann architecture to some point. This is generally seen as a feature, as the notion of "von Neumann" itself has evolved substantially over time such that many historical practices are no longer meaningful (example: overlays). For the last 2 decades, it's been considered Industry Best Practice to do this, as we're increasingly finding we don't want the limitations of this classical architecture to limit our computations or computers. For example, it's quite easy to push computations to GPUs or TPUs in Haskell because by default it doesn't force assumptions onto users about what state means. > causing all kinds of frictions, for which monads and other syntactic sugar were invented No, Monads were not invented to solve this problem in Haskell. They were a subsequent improvement to the original solution. > while Turing complete, it has some weird properties, making it difficult or inefficient to change communication between various components that are using deep function calls when such a need arises in the future. This is quite untrue. And if it were true then it's quite a curious chain of events that functional composition has only become more mainstream and relied upon in many languages, and before the proliferation of closures and functional composition frameworks and techniques (e.g., Dependency Injection) came into being to model the kinds of interactions composed functions make natural. > This leads to using mutable "shortcuts" that render a lot of advantages functional programming might have had useless and starts resembling imperative/OOP programming with its issues again I am surely not alone in having no idea what you're talking about other than perhaps the occasional use of unsafePerformIO in haskell, but even then. > - trivial things like IO can't be modeled without side-effects, so any software requiring input from keyboard, loading external files etc. can't be pure Monads are a way of modeling impure computation purely. And IO is a side effect. It's absolutely wrong to suggest the IO monad is some short of shortcut or inherently impure, or that it's deficient in any way compared to a block of Javascript for modeling the real world. None of that is true. > - often functional constructs make code unreadable despite readability being one of the main reasons for its existence This is a matter of opinion and training. One could make the same argument of React/Redux reducers (really, the state transitions are in the actions?), Google's Guice DI framework (what is happening), or elaborate builder-notation spec framework tests. Most people will find languages like Clojure or Ocaml pretty familiar. What I will agree with is that languages that more closely model referential transparency tend to appeal to some tools modeled after category theory that require up-front study to really understand and apply. Most languages have one or two things like this: Ruby has proc vs block, Python has many arbitrary restrictions and list comprehensions, C has pointers, C++ has generics, Java has reflection, Javascript has callbacks, Haskell has Functor->Applicative->Monad. > - bottom-up creation of algorithms is preferred by many language authors, making it difficult for beginners This has nothing to do with FP and everything to do with programming in a modular fashion. Every language with modules naturally leads people to bottom up styles. That includes Javascript. > - if you really want to know how it works, it takes 5+ years PhD level of studies in abstract math The Haskell compiler is a big, complex piece of work. But so is the C++ compiler, the Java JVM is surely bigger, the CLR is fantastically complex, and have you ever looked at some of the bugs in the Python interpreter? Of course it takes dedicated study to understand a modern compiler. That's only natural. > Disclaimer: I approach 100 languages I've used in production, Okay. 100. > worked for companies that created some of the most popular languages and hate them all Who? Maybe we've worked together. > I hope to work on AI-assisted language creation in the near future. You're very late to the starting line here.
- jeffreyrogers 9y agoEvery discussion I've seen about functional programming is entirely divorced from the practicalities of real programming.
- AnimalMuppet 9y agoOK, I'll bite. Here's the essential truth of functional programming, applicable to all of real programming: Constrain your state space or die.
- shiado 9y agoIn university I was obsessed with Haskell and being clever and writing code that was an unholy stack of lambda functions and fancy constructs like monads and monad lifting. I used the typical intellectual supremacy argument inherent to many fields of study where you reason that something isn't used in industry because industry people are stupid and cannot possibly grasp all these advanced abstract concepts. Eventually I realized that Haskell code is slow to write, hard to reason about efficiency, lazy evaluation sucks for most things, and most importantly Haskell is hard to read by others. Going on Hoogle to look up some package and seeing some abandoned doctoral thesis used by nobody where the only documentation is types becomes exhausting after a while. Go is now my favorite language.
- deleted 9y ago[deleted]
- nilkn 9y agoSurely there's a middle ground here. Most code written by university students in any language is problematic and not professional-quality. The specific deficiencies exhibited may vary from language to language. The extreme you illustrate here is clearly undesirable in any professional context, but that doesn't mean it reflects the code written by any professional Haskell developers out there.
- hateduser2 9y agoYea to me his comment reads as a whiplash to realizing some of the downfalls of haskell. But he seems like he takes it way too far.
- milesvp 9y agoI dunno, not being able to reason about performance is a pretty big deal. I've only ever fantasized about learning haskell, but I can tell you that this quality is what makes sql (or god forbid an ORM) a pain to deal with in production. The explain plan for a given sql query can change on you for no reason other than your table has grown. You can go from using an index for speedy queries to a full table scan because your sql engine decided to no longer use any of your indexes. I don't know what the equivalent cases might be for a more general purpose language, but I strongly suspect it's a problem all declarative languages suffer from.
- proc0 9y agoit's the only thing you can use if you want to write imperative style within pure FP. Obviously a simple example like that makes no difference, but with a giant app, if you eliminate mutations you get many benefits, and in such apps, sometimes you want to express things imperative, but still not mutate. So in other words, Monads are obviously useful, because the first assumption is that mutation is the root of most bugs, so you eliminate it but still use Monads to emulate it.
- e12e 9y agoMaybe.
- classics2 9y agoPseudo-intellectual masturbation.
- ggm 9y agoI have been told a story that some CS courses trying to upscale to FP as the birth language have people teaching inside the IO monad to preserve imperative order, such that the graduates come out coding a strongly typed language almost completely bound in imperative systems design. I feel the moments of clarity for me around the roles of monadic elements in a program are like brainwaves which vanish as soon as I try to grasp them. Right now, I'm stuck on the idea my FP colleague described as the boundary of the real-world, the thing which follows time order and cannot be gone back to in time or sequence. Most FP example fragments do things inside a domain of existence which is bounded solely by the variables of the problem. Solving a fibinnaci for some n thousand integers left in memory is distinctly unlike processing a UNIX pipe sequence yet the latter is said to be very like functional composition.
- tathougies 9y agoThe answer to the posters question is yes... monads are a waste of time if you're using them to handle state changes. It's best to just use explicit threading in that case. The only time (I think) it's okay to use stateful monads in haskell is when it simplifies the code syntactically by removing extra cruft. Otherwise, explicit state is always going to be clearer to understand. On the other hand, most uses of monads in Haskell are not to handle state. In my Haskell SQL library Beam[1] for example, we use monads to build a relational algebra AST at run-time and then dynamically optimize it. The SQL generating system inspects branches of the AST at run-time to generate sensible SQL expressions. Because the DSL is implemented as a monad, we get a bunch of stuff for free. At my work for example, we use a straightforward haskell `forM` to generate large joins. Because of the Haskell purity, we can know for sure that re-executing parts of the AST will not be dispruptive, because the code is pure. I'm currently working on a little utility library for editing rich text with Haskell and I've used the continuation monad to automatically derive a zipper for my data structure. I get O(1) updates at my current position, for free. All I have to do is write a little interpreter. Because of Haskell's purity, I get a lot of functionality without doing anything. This is actually a big deal, as the same implementation in an imperative language involves complicated data structures and O(log n) complexity (look at the GTK text btree source file [2] for the kind of complexity I'm talking about). Because of the flexibility involved with the underlying monad, I have a 'fast' implementation of my zipper for simply modifying text, a 'visual' implementation that records a list of DOM updates to visualize the text as its being edited, and a 'network' implementation that outputs a list of commands for suitable editing. One simple data structure, one monad, three interpreters, and I have a collaborative text editing system. Ultimately, the point is that you should only use an abstraction if it simplifies your code or reduces the error surface. If it does neither, then it's wasteful [1] https://github.com/tathougies/beam https://github.com/tathougies/beam [2] https://github.com/GNOME/gtk/blob/master/gtk/gtktextbtree.c https://github.com/GNOME/gtk/blob/master/gtk/gtktextbtree.c
- kmelva 9y ago> I'm currently working on a little utility library for editing rich text with Haskell and I've used the continuation monad to automatically derive a zipper for my data structure. Could you go into more detail about this?
- deathrip 9y agoHow is this related to Monads? This is an argument against mutation, or saying that Haskell doesn't handle mutation better than js, which is absolutely true; mutation is heavily discouraged in pure FP... Monads can be utilized to encapsulate the concept of sequential computation - if that sequential computation happens to be mutations you're gonna have a bad time.