Live data from Hacker News

Pedagogical Downsides of Haskell

ciobaca.substack.com

111–118 of 118 posts

Re: Pedagogical Downsides of Haskell

#111

I find its syntax & idiomatic style incredibly difficult to follow, in a way nearly no other languages have been for me, including some functional languages (OCaml doesn't seem nearly as bad to me, for instance). It's sometimes implied that those who trip over Haskell just aren't big-brained enough to understand various important concepts related to it, but I've found they're usually very easy to grasp, provided the…

> I'm not sure it's the whole thing, but I think I've also figured out that I find algorithm-type reasoning far easier to follow and work with than equations or proofs.

For me it's the opposite. Once i figure out what an expression is, I do not want it to change on the next clock cycle.

Re: Pedagogical Downsides of Haskell

#112

The pedagogical downside of Haskell is that it ignores the physical reality of the machine. Physically, a computer is imperative, has mutating state, and is filled with all kinds of possible race conditions. Even after you apply the operating system, allowing processes to live together (and giving you space to define new ones), very few constraints are placed on your program and process space. Instead of building on…

> Physically, a computer is imperative, has mutating state, and is filled with all kinds of possible race conditions.

Those are too difficult for compiler writers to reason about. While you're mutating the finite set of registers in your high-level C code - just like a real computer does - clang is swapping those out for operations on an infinite number of immutable registers.

Re: Pedagogical Downsides of Haskell

#113
post #48
post #5

Point 11 surprised me. Not the “go” thing but the “where” syntax – I wish more languages had it!

Yes. Where is often lovely -- I want to delegate details, and not think about them yet, but keep that delegation scoped to the function that needs the relevant details. But calling auxiliary functions "go" is almost always bad naming.

> But calling auxiliary functions "go" is almost always bad naming.

Calling auxiliary functions "go" is like calling loop variables "i".

Re: Pedagogical Downsides of Haskell

#114
post #48

Earlier quoted context omitted.

Yes. Where is often lovely -- I want to delegate details, and not think about them yet, but keep that delegation scoped to the function that needs the relevant details. But calling auxiliary functions "go" is almost always bad naming.

"go" is a fantastic name for communicating that all you're doing is exactly what the containing named definition promises. It's a lot better than adding "Worker" or "Impl" as a suffix of the same name as the parent. It contains no additional information because there's no additional information to contain - the parent name already says it all. So you might as well make it short and a standard idiom.

You're not doing what the parent definition promises though -- if you were you'd leave out the parent definition and the where, and just write the go definition with the true name.

Go is instead doing something similar to the parent that is easily transformed to the right thing (i.e. accumulated in reverse or something), or more general that does the right thing when called with specific arguments. Communicating how and why the function does what it does and works in conjunction with the top level wrapper actually matters.

Re: Pedagogical Downsides of Haskell

#115
post #113
post #48

Earlier quoted context omitted.

Yes. Where is often lovely -- I want to delegate details, and not think about them yet, but keep that delegation scoped to the function that needs the relevant details. But calling auxiliary functions "go" is almost always bad naming.

> But calling auxiliary functions "go" is almost always bad naming. Calling auxiliary functions "go" is like calling loop variables "i".

No, it's really not. An index variable has very little details to it -- there's nothing to communicate.

Auxiliary functions are complex behavior that should be reflected in the name.

Re: Pedagogical Downsides of Haskell

#116
post #115
post #113

Earlier quoted context omitted.

> But calling auxiliary functions "go" is almost always bad naming. Calling auxiliary functions "go" is like calling loop variables "i".

No, it's really not. An index variable has very little details to it -- there's nothing to communicate. Auxiliary functions are complex behavior that should be reflected in the name.

They get their name from the function they are auxiliary to.

Re: Pedagogical Downsides of Haskell

#117
post #114

Earlier quoted context omitted.

"go" is a fantastic name for communicating that all you're doing is exactly what the containing named definition promises. It's a lot better than adding "Worker" or "Impl" as a suffix of the same name as the parent. It contains no additional information because there's no additional information to contain - the parent name already says it all. So you might as well make it short and a standard idiom.

You're not doing what the parent definition promises though -- if you were you'd leave out the parent definition and the where, and just write the go definition with the true name. Go is instead doing something similar to the parent that is easily transformed to the right thing (i.e. accumulated in reverse or something), or more general that does the right thing when called with specific arguments. Communicating how…

Yes, you're doing what the parent promises. You're setting up some initial values for internal accumulators and closing over values that don't change in preparation for the loop. Then maybe you do a bit of cleanup after the loop.

But it's no more interesting than a "for" or "while" loop that takes up most of the body of a function in C or Java. People don't demand descriptive names for those, because they realize such a name would contain no useful information. That's equally true in functional programming.

Re: Pedagogical Downsides of Haskell

#118
post #103

Earlier quoted context omitted.

> Given that a monad is an interface for sequential computation, a much better name would be something like "Seq", "SeqComp", or something like that. Just because you can look at something as describing a computation doesn't mean you always should. For example: data BinaryTree x = | Leaf x | Node (BinaryTree x) (BinaryTree x) instance Monad BinaryTree where return :: a -> BinaryTree a return x = Leaf x bind :: (a ->…

The tree is a tree, but the Monad instance is sequencing modifications to the tree.

Sure, Kleisli arrows `a -> m b` are generally best interpreted in a computational sense. But with something like `IO`, the actual objects `m b` are computations as well, and this intuition is not as broadly applicable.
Post reply on HN