5 ms·
Thanks for that, I can see these things would be useful - but are they a 'killer app'? Like it seems a lot of work to figure out the abstraction to build the mo
by chadcmulligan 9y ago
Thanks for that, I can see these things would be useful - but are they a 'killer app'? Like it seems a lot of work to figure out the abstraction to build the monad, when I don't really need to do this, cause I only have to do this one thing. Or are there a bunch of monads people have already figured out? and I can say when I strike this problem I can use this monad write a few lines of code and go home? Maybe thats the goal? I can see technically its interesting but I can't see a really good reason to spend a lot of time learning this (and I am curious about them). Or are these tools for compiler writers and they'll filter down to us mere mortals? Like Swift can define types as optionals, which sort of looks like the Maybe in haskell (to me any way).
Edit: Like I started out as a C programmer, and then objects came along and I could see that would be useful because it localised the namespace among other things, then generics came along and they were instantly useful, languages have a lot of functional operations like first class functions and they're useful. Like all these things seemed obvious that they'd help write good code, Monads I just can't see why they're good - you've given a couple of examples and they seem useful, though they're not things I can't do with other language constructs, perhaps not as elegantly. I'm wondering if I'm missing something huge? :-)
- deleted 9y ago[deleted]
- KirinDave 9y ago> Thanks for that, I can see these things would be useful - but are they a 'killer app'? Like it seems a lot of work to figure out the abstraction to build the monad, when I don't really need to do this, cause I only have to do this one thing. Most of the core monads are already done. You make new ones to define new compositions of new ones and bring in new features. I've only ever needed to make a genuinely novel monad once. You often don't even make custom monads, you make custom typeclasses that explain how to do your work within a monad, and then pick the ones you want. > and I can say when I strike this problem I can use this monad write a few lines of code and go home? Maybe thats the goal? It is. But as I said, a lot of time what you're actually dealing with is a custom transformer stack with either Identity or IO at its root. So you just write generically and specify what you want. In practice, it's not very difficult. > Like Swift can define types as optionals, which sort of looks like the Maybe in haskell (to me any way). They are. Good example. > Monads I just can't see why they're good - you've given a couple of examples and they seem useful, though they're not things I can't do with other language constructs, perhaps not as elegantly. What's incredibly hard to do is write code that's generic in this axis. There are other examples exercising these principles and pretty amazing things can fall out of that. For example, lenses use a weaker abstraction (functors)and they can make a function that depending on how its' called, either gets a value inside a struct or rebuilds the struct with a new value. Pretty amazing! > I'm wondering if I'm missing something huge? :-) Maybe. But as many people have noted, Haskell is a comittee language that is surprisingly good as an accident of its features all happening to stack together in a somewhat unplanned way. So there is more to the story than this, but this IS a pretty unheard-of story.
- chadcmulligan 9y agowell thanks very much for that, you have piqued my curiosity (again :-)), time to get out that haskell book, and finish it this time. If nothing else its a whole new set of language constructs that I'm sure will come in handy some day, I am starting to see how they could be used. The idea of being able to stack monads to do something sounds intriguing. Or is there a better language to learn?
- KirinDave 9y agoYou might start with PureScript, which is much smaller and runs in browsers and on Node. There's also Idris if you want to see what driving a not-quite-complete future hovercar is like.
- chadcmulligan 9y agothanks, think I'm starting to see, so with one sort of Monad I can chain a bunch of functions together and carry along things like an error value (or a null), and just skip out of the chain if an error occurs but without worrying about a bunch of if tests. That seems useful :-). The do syntax makes the chaining a lot more friendly than in other languages.
- bweitzman 9y agoI think the killer app of the monad is really the language feature that Haskell has called "do notation". This is where it really shines. You can definitely use the monad interface in other languages, but it can feel clunky and unintuitive sometimes because you end up either foregoing some of the effectiveness to better fit the language, or you end up in essentially callback hell. Example: In Haskell, you can use do notation: do x <- someFunction y <- anotherFunction x z <- yetOneMoreFunction y x return (x + y + z) This is syntactic sugar for something like (using `flatMap` in place of >>= (bind) ): flatMap someFunction (\x -> anotherFunction x (\y -> yetOneMoreFunction y x -> (\z -> return (x + y + z) ) ) ) If Haskell programmers had to write code like this (which is what monads look like in other languages), there's no way they would use monads! In languages with objects, you can sometimes get away a minor victory by using what I'll call a "shallow bind". Consider promises in javascript (which form a monad with unit a = Promise.resolve(a) and flatMap p f = p.then(f) ): someHttpRequest().then( response => { if (response.body == undefined) { return Promise.reject("no body error"); } else { return Promise.resolve(response.body); } }).then(body => { try { return Promise.resolve(JSON.parse(body)); } catch (e) { return Promise.reject(e); } }).then(parsed => { if (parsed.status == undefined) { return Promise.reject("no status"); } else if (parsed.status == 500) { return Promise.reject("server failure"); } else { return Promise.resolve(data); } // what would you do if you decided you wanted to reference `response` here somewhere? }); This is definitely an improvement over a deeply nested callback style from 10 years ago, but it does sacrifice some flexibility. You can't refer to previously handled promises because the callbacks are shallow. You can do that with do-notation, and that's what makes the concept of monads stick in Haskell. Once you have that, and in Haskell, it's amazingly implemented as an overloadable piece of syntax, the doors are wide open. Example: at my work, we use free monads to get a similar effect as dependency injection in other languages (clean separation of concerns, easy mocking, etc) but with two huge benefits: 1. Any function is limited to using only the dependencies/effects you allow it to, it won't type check if you try to sneak something in, and 2. Because of the overloadable syntax, we use it to collect timing info on all of our operations that are doing IO in a way where we get a flame graph style hierarchy of effects _for free_. We never have to specify when to start and a stop the timers, the syntax knows when to. It's pretty powerful.