I feel like Haskell is easier to use than it is to explain, and in my experience a lot of these kind of tutorial / explanations actually make things seem harder and more complicated than just working with the concepts and observing what they do. (This one included.)
Why are there so few practical, example and code driven tutorials? I've never run across a succinct "build Twitter with Haskell" in the wild.
Functors, Applicatives, and Monads
41–50 of 90 posts
Re: Functors, Applicatives, and Monads
#42Earlier quoted context omitted.
I'm not familiar with Haskell and am really, really struggling to follow the article. In the case of the functor, the author doesn't explain in technical, specific enough terms the difference between "open the box, extract the value out of it, apply the function, and put the result back in a box" and "apply a function to a box directly; no need to perform all the steps ourselves." I have no idea what 'apply a functio…
The number one mistake is everyone trying to explain a Haskell concept to the general population makes is using Haskell. If someone already knows Haskell there is a good chance they know there concepts. Don't use Haskell as the language, use js to explain it. The number two mistake people make is being aware of the number one mistake so they go write yet another Monad tutorial in Javascript (or Java or whatever...).…
I was lucky seeing this before hitting submit button. Phew that was close.
Re: Functors, Applicatives, and Monads
#43The problem with Monads etc. is that they're simple concepts with extremely confusing names. Monad should be FlatMappable. Once it has the correct name it barely even needs an explanation at all.
Re: Functors, Applicatives, and Monads
#44Earlier quoted context omitted.
A list [b] is a container for bs indexed by integers. A function a->b is a container for bs indexed by as.
> A function a->b is a container for bs Anecdotally, this is one of those things that's trivially true to some people, but really hard for other people to internalize. I think it's why the "container" can lead people astray- if you haven't internalized the idea of functions as being indexed by their argument, it's a really mind twisting thing to try to make that leap.
The reverse though is useful, a container looks like a function that takes one or more indices and returns a value or element.
Re: Functors, Applicatives, and Monads
#45I’m not sure this is intelligible to laypeople. ;)
Re: Functors, Applicatives, and Monads
#46The problem with Monads etc. is that they're simple concepts with extremely confusing names. Monad should be FlatMappable. Once it has the correct name it barely even needs an explanation at all.
Though it would help if more people were aware that a 'nice' way to 'unnest' a functor (F F x -> F x) is really all that it takes to have a Monad.
Re: Functors, Applicatives, and Monads
#47Earlier quoted context omitted.
Why are there so few practical, example and code driven tutorials? I've never run across a succinct "build Twitter with Haskell" in the wild.
Yes, I really need a real word Haskell project simple enough to understand all the math concept. Like, I don't know when to implement the Monad type-class to my domain data types. For example, taking the twitter example, if I have Tweet data type: - should I implement the Monad, Applicative or Functor type class? - How would that help in the big picture? - What if I don't do it? All these funny example of boxes, burr…
I struggled with this when I first learned Haskell. The answer is "yes, if you can". If you have a type, and you can think of a sane way to implement `pure`, `fmap`, and `bind` that doesn't break the algebraic laws, then there's really no drawback. Same for any typeclass. It gives users access to utility functions that you might not really have to document (because they follow a standard interface) and you might not even have to maintain (when you can just use `deriving`).
Doing so will let you/users write cleaner code by allowing use of familiar tools like `do` notation, or functions from libraries that say they'll work for any Monad. It saves you from coming up with new names for those functions, and saves users from having to learn them; if I see something's a Monad, I know I can just use `do` notation; if I see something's a Monoid, I know I can get an empty one with `mempty` and use `fold` with it. As long as it's not a really strange Monad, and it doesn't break any laws, it probably just works the way it looks like it does.
If you can define `bind` et. al., but it breaks the laws, it means the abstraction is leaky - things might not work as expected, or they might work subtly differently when someone refactors the code. Probably don't do that.
If you don't implement a typeclass that you could have, it just means you might have written some code where you could've used something out of the box. Same as going through old code and realizing "this giant for-loop could've just been a few function calls if I used underscore/functools or generators".
That said, it's not too common to stumble on a whole new Monad. The Tweet type probably isn't a Monad - what does it mean for a Tweet to be parameterized on another type like `Int`, as in `Tweet`? What would it mean to `flatMap`(`bind`) a function like `Int -> Tweet` on it? A Tweet is probably just a Tweet. On the other hand, it's a little easier to imagine what a `JSON` might be, and what applying a function like `Int -> JSON` to it might reasonably do. Or what applying an `Int -> Graph` to a `Graph` might do.
Most Monads in practice are combinations of well known ones. Usually you'll be writing some procedural code in IO, or working with a parser, and realize "I'm writing a lot of code checking for errors", "I'm tired of explicitly passing this same argument", or "I need some temporary mutable storage", or some other Effect - so you wrap up the Monad you're using with a Monad Transformer like `ExceptT`, `ReaderT`, or `StateT` in a `newtype`, derive a bunch of typeclasses, and then just delete a bunch of messy code.
Re: Functors, Applicatives, and Monads
#48For some reason everyone likes to talk about Monads, but really the other types here are just as interesting. For example, Applicatives are less dynamic than Monads in that you can't `flatMap`/`bind` to decide on the "next" thing to evaluate based on the previous value, but in exchange you get a "static" tree (or graph) of Applicatives that lends itself much better to static analysis, optimization, parallelism, and s…
I don't know if it's a matter of personality or aura. Monads are the first unfamiliar/complicated abstraction you're bumping into when learning Haskell. You can't do anything IO without monads, and they're not straightforward like functors or monoids. This is probably why there are more discussions about monads.
Re: Functors, Applicatives, and Monads
#49Earlier quoted context omitted.
A list [b] is a container for bs indexed by integers. A function a->b is a container for bs indexed by as.
> A function a->b is a container for bs Anecdotally, this is one of those things that's trivially true to some people, but really hard for other people to internalize. I think it's why the "container" can lead people astray- if you haven't internalized the idea of functions as being indexed by their argument, it's a really mind twisting thing to try to make that leap.
Two stepping stones might be array getters (function that's array-ish), and arrays with an indexed default value function (array that's function-ish)?
Re: Functors, Applicatives, and Monads
#50monads are the MCP of functional programming—no one really knows what they are but everyone writes an article about them using analogies that break when you actually use them in practice.
Nah. Lots of people know what monads are. And critically, they don't write monad explainers. This is because if you understand the fundamentals well enough to understand an explanation, monads are so trivially straightforward that the definition is 100% of the explanation you need. Learn about how Haskell denotes types. Learn about higher-order functions, higher-kinded types, parametric polymorphism, and bounded poly…
Except that's not the case because most people know all of those concepts from their main language, and don't know what a monad is.
Higher order functions yup. A function can take a funtion as an argument and correctly assign the argument type (unless C where you can finagle it but it's not first class).
Higher-kinded types? Yup. Prettt much half of "generics". Taking C# that essentially the idea that List is a "type constructor" that allows you to construct a type. If you specify Integer as the T you can say something like List and you get a type which is a list of integers.
Parametric polymorphism? Yup. When defining function - for example using List. You can define the implementation of the function using the generic parameter "T" and not have to specify if you are defining the implementation on a list of Integers or a List of String, and the single implementation will work for all of them.
Bounded polymorphism? Yup. Again using C#, you can specify a restring on the "T" type parameter. Instead of saying "T" can be any type at all, you can add a "where" clause that says "T" must implement the ISerializable interface, or it must be a subclass of Foo class.
So most people will read this list. And say "huh, I guess I do already know all of those concepts but by different names." But that doesn't mean they understand Monads conceptually, when to use them nor why. Even if those things are required to read the Monad definition, there is more there.
A rough analogy, but it's like saying people know the visitor or facade design pattern just by reading their type signature. Oh and if instead of having intuitive names their names useless names like "foblax" and "grobalum" design patterns.