29 ms·
Haskell Concepts in One Sentence
- jpt4 10y agoArticle appears to be in flux; definition of lazy evaluation changed.
- crystalPalace 10y agoMy change is reflected in my use of "Last Updated 3/25/2017" and in my commit message. Thank you for ensuring transparency.
- bonoetmalo 10y agoWe should probably add a sentence about not using fixed margins that will make the text body 1/5th the width of my screen.
- crystalPalace 10y agoMy apologies, I nixed the hardcoded 100px margins and used percentages instead.
- iamwil 10y agoIt'd help beginners if there was a sentence explaining what fmap is.
- m-j-fox 10y agoOr morphism.
- hzjavier 10y agoAgree. Also, order can improve. You talk about pure functions on the first sentence. Later you explain what a pure function is. Explaining pure functions before monads can help. Same case for functors.
- chrisdone 10y agoIn Haskell and PureScript, `fmap` is a method in the `Functor` class, which is defined by class Functor f where fmap :: (a -> b) -> f a -> f b for which instances should satisfy `fmap id = id` (and you get `fmap (g . f) = fmap g . fmap f` for free). If you can find a type for which you can implement `fmap` and satisfy the laws, then you have an instance of `Functor`. That's the precise and short definition. It assumes the following knowledge: 0. How partial application works and the . works. 1. How Haskell's type-classes work (`Functor`). 2. How Haskell's methods work (`fmap`). 3. How Haskell's higher-kinded types work (the `f`). So good luck explaining `fmap` in one sentence unless you already know Haskell and understand its type system to a confident degree, which depending on your background can take weeks to months.
- iamwil 10y agoThere's often no need to explain everything in detail to get the gist.
- jnordwick 10y agoMy general problem with Haskell articles and such: they are written as if you already understand Haskell. They make total sense if you know the language, but if you are trying to learn are mostly useless if not more confusing. Or even worse, they devolve into dense academic prose even when writing introductory articles. Sometimes they even use Haskell as if you already know it to try to explain it. I'm still looking for a basic article that describes monads well. My first few languages were all functional too, so that isn't the problem. I even still use APL derivatives.
- seagreen 10y agohttp://dev.stephendiehl.com/hask/#monads http://dev.stephendiehl.com/hask/#monads
- jnordwick 10y agoAre you serious? > Monads are not complicated. They are implemented as a typeclass with two methods, return and (>>=) (pronounced "bind"). In order to implement a Monad instance, these two functions must be defined in accordance with the arity described in the typeclass definition: This is a great example of what I just said: it uses complex Haskell code and functions to describe a monad. If you already know what it assumes you know, you most likely already know what a monad is.
- setra 10y agoIf I define this in c++ lingo words barely change. You take a c++ parent class with two virtual methods. These methods are "return" and "bind". In order to implement a monad instance you must derive from this parents class and implement the virtual methods.
- jnordwick 10y agoWhat is bind and what is return? What do they do?
- dmead 10y agowhats the third function for a monad? bind return and...?
- setra 10y ago(>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b There are two forms of bind. The >> function is used when the function does not need the value produced by the first monadic operator.
- mrkgnao 10y agoThe "categorical" definition of monads uses return and, instead of bind, join :: m(m a) -> m a You don't need to specify it if you already have bind/>>= and return/pure, since they can be derived from each other. For instance, purely by "following the types", f :: a -> m b fmap f :: m a -> m (m b) join (fmap f) :: m a -> m b In other words, (>>=) :: m a -> (a -> m b) -> m b ma >>= f = join (fmap f ma) is a perfectly good definition of bind I you have join.
- gizmo686 10y agoHaskell does have "fail" as part of the Monad typeclass. But it is being depreciated and moved into the MonadFail class. Haskell's Monad also has >> and >>= both defined as part of the typeclass itself; instead of making >> a normal function. The typeclass does provide a default implementation of >> in terms of >>=. But you are correct. In general all you need for a monad is bind and return. http://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#t:Monad http://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude...
- platz 10y agoThat's all you need to make the compiler happy, but it's not a monad without satisfying the laws too
- scottmsul 10y agoA monad is any data structure which implements bind. Bind is a higher-order function with two parameters - one is the data structure to be transformed, the other is a function which maps over elements in the data structure. However, unlike a normal map, each result of "bind" sits in its own version of the original data structure, which then have to be combined back into a single data structure. The way in which the data structures are combined is what makes each monad different. For example, List is a monad. Suppose we had a List of Ints, such as [5,3,4]. If we were to run bind over this list, we would need a function that takes an Int and returns a List of something. We could use "show", the function which converts Ints to Strings (a String is technically a List of Char. Since this is a List, we're good). If we call bind using [5,3,4] and show, we get ["5","3","4"] which are then combined to "534". We can check with the interpreter (>>= is bind): Prelude> [5,3,4] >>= show "534"
- jnordwick 10y ago> each result of "bind" sits in its own version of the original data structure, which then have to be combined back into a single data structure That doesn't make sense to me. Let's say I have the list [5,3,4], to me that means each application returns a three element list [f(5),x,x], [x,f(3),x], and [x,x,f(4)] then the bind function takes these lists and turns them into [f(5),f(3),f(4)]. What makes this function a monad?
- scottmsul 10y agoIt makes a List of Lists, then combines those into a List. [5,3,4] becomes [f(5), f(3), f(4)], but f(x) must return a List. Those inner Lists are then concatenated. When I say "original data structure", I mean the type of data structure is the same (in this case, List).
- jnordwick 10y agoWhat is the data structures don't support a join operation, like a tree?
- nickpsecurity 10y agoHmm. They certainly have a naming and explanation problem in Haskell land. Some impressions from a few of these better explanations. "A monad is composed of three functions and encodes control flow which allows pure functions to be strung together." Gibberish compared to claim that monads just execute functions in a specified order. Aka an imperative function or procedure by one definition I've seen a lot. Of course, that monad definition might be wrong, too. "A recursive function is a function that calls itself inside its own definition." That's a recursive definition lol. Must have been a joke. "A monad transformer allows you to stack more than one monad for use in a function." We've had composition of procedures for a long time. Perhaps Haskell could've called it a MonadComposer? "Lift is an operation on a functor that uses fmap to operate on the data contained in the functor." fmap-apply() or something like that? "Optics(lens and prisms) allow you to get and set data in a data type." Getters and setters. My early OOP/C++ books are finally more intuitive than something. "Map applies a function to every element of a list." foreach(function(), list) "A predicate is a function that returns true or false." A boolean function. "Filter applies a predicate to a list and returns only elements which return true." Syntactic sugar for a foreach(function, list()) where the function on each member is an If (Conditional) is TRUE Then AddElementToNewListThatsReturned(). Yeah, even the description of imperative version is getting long. This might be a productivity boost. "A morphism is a transformation from any object to any other object." A cast from one object to another? Or one with an actual conversion function and/or check? The functional name seems more accurate, though. "Algebraic data types are a method to describe the structure of types." Ahh, they're just structs. Wait, what is a type exactly? And therefore what is an abstract... oh darn... "Free monads allow the transformation of functors to monads." A functor is an object that can be fmaped over. We covered map. Maybe the same. A monad is either an ordering of functions or something composed of three functions and encodes control flow composed of pure functions. Free monads are apparently an unknown thing that can transform objects that can be fmaped over into something composed of three functions with encoded control flow of composed, pure functions. I heard a lot of good Masters and Ph.D. proposals before this one. This is good, though. Especially quantifying the unknown aspects with a lot of NSF-funded R&D. "A lambda is an unnamed function." "Types are an inherent characteristic of every Haskell expression." "Currying uses partial application to return a function until all arguments are filled." "A category is a collection of objects, morphisms, and the configuration of the morphisms." Ok, I just have fun with that one. Author did good on a lot of them. I'm just going to leave these here as quotes to add to Free Monads in... The Advanced Course: Haskell in Two or More Sentences. They provide anywhere from no information at all to the uninitiated to extra confusion inspiring taking or avoiding Haskell courses. :)
- burticlies 10y agoOne simplistic but useful analogy I've found is that monads are a way to control program flow with functions. A monad is to functional programming what if/else is to imperative. It may not cover all the nitty gritty about what is and isn't a monad. But it gets you a long way to understanding why you might use them.
- hota_mazi 10y ago> A monad is composed of three functions Actually just two (bind and return). And three laws which are typically not captured in the type system and which must therefore be tested separately.
- init0 10y agoJargon from the functional programming world in simple terms! http://git.io/fp-jargons http://git.io/fp-jargons
- a_imho 10y agoThe problem when starting out with Haskell is that you can't google type errors.
- edem 10y agoThis is all useless for someone without haskell experience.
- Cybiote 10y agoThis is a good start and might be useful to other beginners. From the vantage point of someone who already knows what the words mean, I can fill in the gaps in your definitions but unfortunately, a beginner might not be so able. Here are some suggestions on how you might close some of those gaps a bit (I think allowing yourself to go over a sentence here and there should be ok). You use fmap more than once without having defined it. Currying: You need to define partial application. Map and filter, I'd use collection instead of list. There is more nuance but that is good enough at this level. Morphisms generalize the concept of function. They can be thought of as capturing structure (such as a set equipped with + and 0) preserving maps (which is something analogies try to do). lazy evaluation could do with mentioning thunk, then you'd have to define what a thunk is, of course. Fold: Folds are a lot more interesting and it's not clear what you mean by your given definition. I suggest defining it in terms of structural recursion. Category: It's worth defining what objects mean to a category. As well, explicitly mentioning the laws of identity, composition and associativity rather than just the nebulous wording of configuration would be beneficial. Functor: A more useful foundation is in thinking of functors as morphisms between categories. Types: There is much more to types than this. Wrong in the correct direction is to think of types in terms of sets. Better yet, as propositions. Type Classes: Since you mention parametric polymorphism, you should also mention ad-hoc polymorphism and how type classes and interfaces are examples. algebraic data types: There's a lot more to algebraic data types than this. After defining sum types and product types elsewhere, you can talk about why such types are called algebraic. parametric polymorphism: what is a type variable? monoid: Moniods also need an identity element, and giving examples is always useful: natural numbers: +,0 or strings: +,"". One reason monoids are of special interest to computing is because they possess associativity, which is useful when parallelizing.
- strictfp 10y agoA monad is a wrapper type designed to alter the semantics of chains of operations performed on its wrapped values.
- aetherspawn 10y agoMonads are not complex. A monad is a box. Any monad has two functions (plus others, imagine this is a minimal interface): bind and return. You can put anything in the box. It's TARDIS-like. `return` replaces the thing that was in the box. `bind` replaces the box. Most monads have a number of functions that can only be executed over boxes. This is because the boxes have special metadata (for example, someone has been scribbling state underneath the box). The 'get' function from the State monad just tells you to read the gibberish on the box instead of unpacking the box. The 'set' function scribbles more stuff on the bottom of the box. Useful monads then provide a function to put things into the box, work with the box and then throw the box away (or inspect it by itself). These are the functions called 'runWhatever' for example 'runState', which lets you put an apple in the box, put a shipping label onto the box and then eventually separate the apple and the shipping label into each hand, throwing the box in the bin. You can put anything in a box. Even more boxes. And when you're inside the box, you can't really tell how deep you are. If you're in the bottom box you can't actually see that you're in 20 layers of boxes, and this is why Monads are so powerful for creating libraries and frameworks.
- aetherspawn 10y agoHere's an extended explanation of how monad 'lift' works: You have a box (one monad). Inside the box is a jar (one monad) and inside the jar is an apple. You want to write on the jar, so you give it to your friend but he's a moron and doesn't know how to open the box. The `lift` function opens the box, gives him the jar so he can write on it, then puts it back in the same box. `lift` is for executing monad stuff within other monads when you have jars in boxes and need to juggle them around a little bit, but all your friends are idiots. `liftM` is the same thing actually, but can be used on the apple in the jar since the apple isn't already a monad. If you need to swap the apple for another apple, but it's inside the jar inside the box, you need to use the composition of `lift` and `liftM` to first take the jar out the box, and then the apple out of the jar (but it'll pack them all up when you're done).
- bogomipz 10y agoThanks for your explanation. I confused as to why so much discussion and blog posts surround the topic of monads as if they were very difficult to understand then? I would be curious to get your thoughts. Also I didn't understand the word TARDIS-like.
- rawicki 10y agoI see traces of OP getting to understand the joke "A monad is just a monoid in the category of endofunctors, what's the problem?" :)
- oblio 10y agoI'm still kind of having problems with monads. Funnily enough, I recently found an article explaining what monoids are: https://fsharpforfunandprofit.com/posts/monoids-without-tears/ https://fsharpforfunandprofit.com/posts/monoids-without-tear... You start with a bunch of things, and some way of combining them two at a time. Rule 1 (Closure): The result of combining two things is always another one of the things. Rule 2 (Associativity): When combining more than two things, which pairwise combination you do first doesn't matter. Rule 3 (Identity element): There is a special thing called "zero" such that when you combine any thing with "zero" you get the original thing back. With these rules in place, we can come back to the definition of a monoid. A "monoid" is just a system that obeys all three rules. Simple! Long explanation overall in the article, but based on 6th grade math. I understood it, and it stuck. Could someone extend the monad explanation from here? Maybe I'll finally get it :)
- aban 10y agoThat's a good explanation of Monoids. You can also watch (at least the first half) of this video for more on Monoids: https://www.youtube.com/watch?v=WsA7GtUQeB8 https://www.youtube.com/watch?v=WsA7GtUQeB8 There are already a good number of people trying to explain Monads in this thread, so I won't attempt it. But I'll say this (in the context of Haskell): In Haskell, like how Monoid is a typeclass, Monad is just another typeclass. So me mentioning "typeclass" twice in a sentence suggests that you probably have to first understand typeclasses and data types. Also, I wouldn't recommend tackling Monad right after grasping Monoid. I'd recommend you read about and understand Functor and Applicative functors first, and that will ease you into understanding Monads and actually why you would want to have them. So, you may want to read these pages from Wikibooks in this order: https://en.wikibooks.org/wiki/Haskell/Classes_and_types https://en.wikibooks.org/wiki/Haskell/Classes_and_types https://en.wikibooks.org/wiki/Haskell/The_Functor_class https://en.wikibooks.org/wiki/Haskell/The_Functor_class https://en.wikibooks.org/wiki/Haskell/Applicative_functors https://en.wikibooks.org/wiki/Haskell/Applicative_functors https://en.wikibooks.org/wiki/Haskell/Applicative_prologue https://en.wikibooks.org/wiki/Haskell/Applicative_prologue The last link is the first section of a chapter on Monads; so use the links on the sidebar to read the subsequent sections of the chapter. Typeclassopedia is another great resource for the typeclasses I mentioned: https://wiki.haskell.org/Typeclassopedia https://wiki.haskell.org/Typeclassopedia
- bogomipz 10y agoThis is brilliant, thanks for sharing.
- csneeky 10y agoWhat an excellent distillation! It isn't uncommon to see someone w̶i̶t̶h̶ ̶a̶ ̶f̶r̶a̶g̶i̶l̶e̶ ̶e̶g̶o̶ explain this stuff in a way that is needlessly complex and full of jargon that scares folks off. Thanks for the great work here. We need more of this kind of thing in the FP world!
- LeanderK 10y agoTo everyone new to haskell and confused: Don't judge haskell based on these definitions. They appear strange and crazy, but when you actually do stuff most of them turn out to be quite intuitive. My advice is to ignore these things. Don't read a million monad tutorials. Just play around and code something, you don't have to understand the monad-definition before you can use the do-notation. Try to ignore them. After a while you get an intuition and then the definitions will make sense.
- deleted 10y ago[deleted]
- freddref 10y agoIt's only intuitive after you understand it ;)
- AsyncAwait 10y agoI've found parser combinators to be a fun and useful way to play around with monads, since it's pretty easy to implement your own monads this way, and what better way to understand something, than to actually make it?
- LeanderK 10y agoi agree! They are also surprisingly useful and not incomprehensible like Regex.
- babbeloski 10y agoQuestion to JS people using Redux. Are the middlewares used to control side effects in actions considered monads? The action returns a description of the side effect, and the middleware handles the actual doing, leaving the programmer to focus on the pure aspects.
- mbfg 10y agoThere is an adage that if you see a lot of advertising for a medicine (think hair regrowth formulas, or pills of reflux disease) you know that none of them are any good. This page makes me wonder about monads in the same way.
- marcosdumay 10y agoDo you think any of those is paid in any way?
- ncphillips 10y agoThese sentences are nice, but I feel like more definitions and some re-ordering could make the document as a whole more meaningful. For example, Lift is defined way before Functor, and fmap is never defined so I had no idea what Lift was about despite that nice concise sentence.
- mpfundstein 10y agoIMO the most accessible resource for learning functional concepts like Functors, Applicatives and Monads is the free online book: https://github.com/MostlyAdequate/mostly-adequate-guide https://github.com/MostlyAdequate/mostly-adequate-guide It uses Javascript to explain everything from scratch. Pure-functions, currying, composition, functors, monads, applicatives and so on. Its free, so check it out. Reading it and understanding the concepts completely changed my whole coding style in the last couple of month. I hope functional javascript becomes more mainstream and we will soon call this stuff 'standard'. Its just too convenient to stack a Future on top of a Reader and get dependency injection + async function handeling without any boilerplate code. P.S. Since ES6, javascript is wonderful. Functional code often really looks like lisp. Pity that we don't have macros (yet, and actually there is a way (sweet.js). P.P.S. If DrBoolean got you hooked. You might want to check Ramda and fantasy-land. The former is a more functional minded underscore/lodash, the latter a specification (and community) for algebraic data structures in javascript to which a lot of new libraries adhere to.
- shadowfacts 10y agoSo far the Mostly Adequate Guide is awesome, it's really well written, easy to understand (so far), and fun to read.
- lolive 10y agoYour comment made me read this book. This book changed my life. A biiiillion thanks !!!!
- leshow 10y agoI'd modify the monoid line to include associativity and identity: A monoid is a a type with an associative function and an identity function