Live data from Hacker News

Pedagogical Downsides of Haskell

ciobaca.substack.com

81–90 of 118 posts

Re: Pedagogical Downsides of Haskell

#81

Earlier quoted context omitted.

I think this article's audience is teachers of beginners, not beginners themselves. At least the author is writing about their experience as a teacher. Don't know why you thought it would be an article for beginners, but good on you for linking a resource regardless.

The article is an introduction to the basic concepts of Haskell, thus beginners may be considered a target audience. However, the style and the content brings to my mind the dreaded monad tutorials. I'm not convinced the article is about pedagogical downsides of specifically Haskell. It mostly reads like a collection of random purported gotchas/differences from someone with experience with other languages.

I'm taking my cue from the title of the article and the intro - seems pretty certain

Re: Pedagogical Downsides of Haskell

#82

Earlier quoted context omitted.

I find the terminology that Haskell uses quite misleading for software engineering. It borrows concepts from category theory with quaint names such as a "monad", "endofunctor", "catamorphism", etc. The problem is that, instead of a "monad", we can say "brrrdogcogfog" and nothing will change -- the name is absolutely irrelevant to the problem being solved. Given that a monad is an interface for sequential computation,…

F# calls them Computation Expressions which is far more approachable imo

That sounds almost as vague to me as “object” does in OOP. Don’t non-monadic functions also consist of expressions that describe computations?

Re: Pedagogical Downsides of Haskell

#83

Earlier quoted context omitted.

As I understand it, monads help solve the problem of sequential computation in Haskell but the concept is not limited to that. For example, how would you consider the monadic properties of data type like Maybe or Either to be (exclusively?) interpreted through the lens of sequential computation? What about commutative monads where the order doesn’t matter?

The `Monad` instance for `Maybe` and `Either` is precisely for doing sequential computation! Consider the following: myBigSubroutine :: Maybe Int -> Maybe Int -> Maybe Bool myBigSubroutine ma mb = do a b) Here we are sequencing the "effect" of optionality. `ma` must be evaluated before `mb` and if it returns a `Nothing` then we short circuit and do not evaluate `mb`.

> `ma` must be evaluated before `mb`

No - either one can be evaluated first, with the other being short-circuited. If you swap the order of those lines, the function is exactly the same (in terms of inputs and outputs, at least).

Re: Pedagogical Downsides of Haskell

#84

Earlier quoted context omitted.

One of the more surprising aspects of GHC Haskell is that it is possible to write a very high level code with performance matching or exceeding code written in a low level language, thus honoring the machine. Stream fusion for an example. Not sure if there is any other language with higher abstraction/performance ratio.

JavaScript comes to mind. Its benchmarks are a wonderful testament to the immense engineering resources poured into V8.

V8 is very impressive. But in exchange for its speed, it needs more memory. JS code optimized for speed tends to use more memory with Node.js than optimized Haskell or OCaml code:

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Re: Pedagogical Downsides of Haskell

#85

Earlier quoted context omitted.

As I understand it, monads help solve the problem of sequential computation in Haskell but the concept is not limited to that. For example, how would you consider the monadic properties of data type like Maybe or Either to be (exclusively?) interpreted through the lens of sequential computation? What about commutative monads where the order doesn’t matter?

The `Monad` instance for `Maybe` and `Either` is precisely for doing sequential computation! Consider the following: myBigSubroutine :: Maybe Int -> Maybe Int -> Maybe Bool myBigSubroutine ma mb = do a b) Here we are sequencing the "effect" of optionality. `ma` must be evaluated before `mb` and if it returns a `Nothing` then we short circuit and do not evaluate `mb`.

I think the commenter who mentioned syntax is on to something. If I write this

    fn my_big_subroutine(ma: Option, mb: Option) -> Option {
        match (ma, mb) {
            (Some(a), Some(b)) => Some(a > b),
            (_, _) => None,
        }
    }
it’s clearer to me what the intent is. I’m not sure why the other syntax is so hard for me but it feels hard to understand for some reason.

Re: Pedagogical Downsides of Haskell

#87

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 find the terminology that Haskell uses quite misleading for software engineering. It borrows concepts from category theory with quaint names such as a "monad", "endofunctor", "catamorphism", etc. The problem is that, instead of a "monad", we can say "brrrdogcogfog" and nothing will change -- the name is absolutely irrelevant to the problem being solved. Given that a monad is an interface for sequential computation,…

> Given that a monad is an interface for sequential computation

And what the hell is an interface for sequential computation? I think I understand what these Maybe types are and what they accomplish but "interface for sequential computation" sounds a lot like those buzzwords people mix together that could mean anything.

Re: Pedagogical Downsides of Haskell

#88

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…

Your language should not care about the physical reality of the machine. That's the compiler's job, and the CPU microcode's job. And thankfully, every programming language ignores physical reality, including Assembly.

The goal of a programming language is to allow a human to express a sufficiently rigorous solution to a problem. From there, every step along the chain of execution is allowed to make 'unobservable' (for various definitions of the word) changes to execution. Your compiler might unroll your loops, or eliminate some unneeded intermediate variable, or even replace your entire function with a lookup table. Your CPU's microcode might do some weird fuckery with predictive execution. You shouldn't care, as long as the solution is, as far as you can observe, identical to your given one.

Whether functional programming is a better expression of computation than imperative programming is its own problem, but it's both silly and wrong to assert that imperative is better because it matches the behavior of the machine.

Re: Pedagogical Downsides of Haskell

#89
post #8
post #7

[flagged]

Can you give an example of a Haskell way that is not Right?

Typeclasses. They're a huge improvement over OO-style overloading, but using them as your default way of talking about structures is a Faustian bargain:

- Implementing two instances of one member each is much more work than one instance with two members, which incentivizes overly coarse typeclass hierarchies: hence Num and friends, which are a disaster.

- They don't provide a good way to talk about one structure uniquely determining another (e.g. a given semigroup can be made a monoid in at most one way), which leads to boilerplate overly pessimistic constraint resolution.

- The way constraint resolution works forces them to take type constructors, not types - which makes aliases, type families, etc. second class citizens.

Re: Pedagogical Downsides of Haskell

#90

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 find the terminology that Haskell uses quite misleading for software engineering. It borrows concepts from category theory with quaint names such as a "monad", "endofunctor", "catamorphism", etc. The problem is that, instead of a "monad", we can say "brrrdogcogfog" and nothing will change -- the name is absolutely irrelevant to the problem being solved. Given that a monad is an interface for sequential computation,…

> 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 -> BinaryTree b) -> BinaryTree a -> BinaryTree b
        bind f (Leaf x) = f x // replace a leaf with the result of calling f on its label
        bind f (Node l r) = Node (bind f l) (bind f r) // traverse down the tree, ultimately replacing all the leaf nodes with a new subtree
You can choose to interpret a binary tree as describing nondeterministic computation where you have two choices at every step, but I rarely do. Most of the time trees are just trees.
Post reply on HN