[HN Gopher] Why is learning functional programming so damned har...
       ___________________________________________________________________
        
       Why is learning functional programming so damned hard? (2019)
        
       Author : allenleein
       Score  : 119 points
       Date   : 2021-08-15 14:06 UTC (8 hours ago)
        
 (HTM) web link (cscalfani.medium.com)
 (TXT) w3m dump (cscalfani.medium.com)
        
       | _query wrote:
       | In my experience when learning functional programming with
       | Haskell there are two kinds of complexity:
       | 
       | 1. Complexity caused by the change of paradigm: This specifically
       | hits programmers with a lot of experience in OOP languages. For
       | getting into the FP-mindset your brain needs a bit of time to get
       | rewired. You need to switch thinking about mutating objects to
       | thinking in mapping streams of data. Given that many OOP
       | languages are adopting functional ideas like map and fold/reduce,
       | nowadays a lot of developers already have a bit of experience in
       | thinking in the FP-way, and this will get better with time.
       | 
       | 2. Complexity caused by the tools: There's a reason the author in
       | the above post started out with Elm instead of Haskell :-)
       | Writing a few recursive functions in haskell is still pretty
       | simple. Where it get's very complex is when you want to build
       | real world applications. To build a simple web app you need to
       | 10s of decision on what tools and libraries to use. Here's a
       | couple questions you'll need to find an answer to when building a
       | haskell app:
       | 
       | - What GHC and what language extensions do I need? How do I
       | install it? - What package manager do I use? Cabal, nix, stack? -
       | What web server library? - What database library do I need? Do I
       | need an ORM, are there even ORMs in haskell even though there are
       | no objects? - What HTML template library to use? - How do I
       | compose it all together? What is a monad stack?
       | 
       | When you have only very few experience in haskell it's really
       | hard to not get stuck here. The quality of documentation of most
       | haskell tools also doesn't very much help here.
       | 
       | I believe that the value haskell can bring is signifcant, and by
       | fixing the tooling situation we can a lot more people to adopt
       | haskell in the future.
       | 
       | With IHP we're trying to fix the tooling situation and build a
       | haskell-based web framework that is as easy to use a rails or
       | laravel :) To combine the benefits of purely-functional
       | programming with the RAD approach of rails, laravel and django.
       | It's now already the most active haskell web framework and we
       | have many people starting their haskell journey with IHP.
       | 
       | We have live reloading in dev mode, a JSX-inspired template
       | language and many code generators to quickly get started with
       | shipping real world apps.
       | 
       | Check out this video of building a simple blog app in IHP:
       | https://www.youtube.com/watch?v=UbDtS_mUMpI To get started
       | (supports macOS, linux, windows) check out the IHP Website:
       | https://ihp.digitallyinduced.com/
        
       | soheil wrote:
       | Honestly a much less gimmicky and concise guide can be found here
       | [0]. The focus is on scala but it does away with longwinded
       | storytelling style explanations and petulant comics. It gets to
       | the point, gives a couple of examples and tells you exactly why
       | each tenant of functional programming is useful in one sentence.
       | 
       | [0] https://nrinaudo.github.io/scala-best-
       | practices/definitions/...
        
       | throwaway81523 wrote:
       | The saying about Haskell is that it has the steepest unlearning
       | curve. It probably helps to have seen some abstract algebra since
       | many of its ideas come from there. The online book
       | learnyouahaskell.com is pretty readable though.
       | 
       | As that guy was a big executive whose time was interchangeable
       | with money, he might have had better luck treating FP as a topic
       | in math that he was having trouble with, and hiring someone for
       | one-on-one tutoring, either in person or online. It might have
       | gotten him through the various stumbling blocks quicker.
        
       | bennysomething wrote:
       | Christ that's a long winded article! Also I'm getting tired of "I
       | learned to program on a stone tablet with a chisel" type stories.
       | Wow, you wrote assembly, swoon!
        
       | agumonkey wrote:
       | culture and the paradox of simplicity
       | 
       | fp and math go abstract fast, people can't see any tangible
       | machine or pragmatic process
       | 
       | fp-ists enjoyed that and pushed it to 11, making it even weirder
        
       | jacquesm wrote:
       | Hot tip: use the stack that you know best if you want to ship.
       | Feel free to experiment with other stuff for
       | hobby/entertainment/educational purposes.
        
       | default-kramer wrote:
       | The author's struggles with Haskell resonate. I suspect it's just
       | a very hard language to learn. I've given up attempting to learn
       | it at least twice now.
       | 
       | I took Martin Odersky's Scala MOOC sometime around 2012-2014 and
       | it was easy. It just made sense and the IDE experience was nice.
       | I would recommend it to anyone who uses C# or Java and wants to
       | learn FP. Although after 8 years I don't know if it's still as
       | good, or if something better has come along. Either way, the
       | course is still available: https://www.coursera.org/learn/scala-
       | functional-programming
       | 
       | Next I worked through SICP and that was the best CS book I've
       | read, although significantly more difficult than the Scala
       | course.
        
       | crvdgc wrote:
       | Specific to the "jargons" the author talked about. I find recent
       | introduction level Haskell books actually do a surprisingly good
       | job covering all the concepts the author mentioned. And they
       | don't suffer from the online learning material problems.
       | 
       | The two books I read and can recommend are _Programming Haskell_
       | by Graham Hutton  & _Get programming with Haskell_ by Will Kurt.
       | 
       | Another source that helped me a lot is the video series _Category
       | Theory_ by Bartosz Milewski [0]. It requires basically no
       | background on category theory and defines all the concepts along
       | the way. Bartosz also uses Haskell code as examples. You only
       | need to know the syntax up to type class to understand.
       | 
       | As for the awful experience people get from learning Haskell, I
       | think it depends a lot on people's expectations.
       | 
       | Most people only learn one language from school or early career,
       | and then migrate their experience from one language to another.
       | You don't learn the concept of "stack" twice, you only "learn"
       | how to express them with a different syntax. So people can
       | "learn" new languages with significantly lower effort than they
       | learned the first language.
       | 
       | And when they find Haskell or other ML-family functional
       | programming languages, they can't find the corresponding concepts
       | in their known language. This time people actually need to learn
       | new concepts as they learned their first language.
       | 
       | The experience is very similar to learning algorithms or OOP
       | design patterns. And I don't think it's harder to learn Haskell
       | up to the level mentioned by the author than e.g. reading the
       | gang-of-four book.
       | 
       | [0]:
       | https://youtube.com/playlist?list=PLbgaMIhjbmEnaH_LTkxLI7FMa...
        
       | lucie_cupcakes wrote:
       | Here is an archive of the text-only view from the article:
       | https://archive.is/aoB1o
        
       | revskill wrote:
       | Why using a StateMonad when i could just use OOP ? Simple,
       | elegance and easier to read, write and test.
        
       | jokethrowaway wrote:
       | As someone who is huge on Functional Programming, I'm not sure
       | you're reaping the benefits you're talking about. Your dedication
       | is impressive, but it's nowhere close to being required to build
       | any kind of product.
       | 
       | Sure, I agree that learning FP will make you a better
       | development, but spending all these learning resources in order
       | to build a product is not very convenient.
       | 
       | I've been shipping code with mediocre languages all my life. Even
       | now, I routinely pick node.js over Haskell or Rust just because
       | the complexity of the solution I need to build is not high enough
       | to justify writing amazing bug-free code. Sure, you may get more
       | bugs and less help from the compiler, but there is more material
       | online and I can easily find a cheap developer to throw at the
       | project.
       | 
       | I've been developing for 15 years. After 5 years of C++, PHP, JS,
       | I decided to jump into Haskell for my side projects. I can't say
       | the learning curve was as hard as you made it out to be: there
       | are plenty of great resources for learning Haskell and you don't
       | need to go through Elm or Purescript (which weren't even a thing
       | when I learnt Haskell). Actually the differences between the
       | languages may make things more confusing.
       | 
       | In the last couple of years I stopped using Haskell completely,
       | simply because Rust (a language designed to build things, unlike
       | Haskell which is more of a language research project) is
       | functional enough, pleasant enough to use and is developing a
       | nice community. The most useful FP concepts trickled down in
       | other languages.
       | 
       | FP already won and nobody even noticed it.
        
       | tel wrote:
       | Learning FP takes real investment both in time spent learning and
       | practicing the concepts and in time spent slowly misusing them in
       | real projects until you develop your taste for where they're
       | appropriate. This investment is regularly underestimated.
       | 
       | Using FP introduces real advantage in terms of taste and
       | simplicity, meaning that "advanced" concepts are not nearly as
       | prevalent as someone who just learned them might hope. The rule
       | of 3 is helpful and under-applied. Programmers new to FP get
       | eager to use cool tech as opposed to leverage improved taste.
       | 
       | FP can be utilized in many languages but in ones that don't guide
       | your hand toward it--your Haskell, your OCaml, your Elm--it's
       | easy to have it "mix" with other styles. It is _not_ the case
       | that combining FP and non-FP styles immediately make sense or
       | work. It _is_ the case that the strengths can be combined if done
       | thoughtfully.
       | 
       | All of these points generalize, though. As with any programming
       | work, taste is important. It takes a while to develop and often
       | needs to be developed within the context of a team. Tasteless FP
       | is an awful, awful waste of time, energy, money.
       | 
       | Someone who likes to throw all the jargon at your is a hobbyist,
       | a proselytizer, or a fan. Not terrible, but not necessarily
       | someone who can yet manage all of the necessary tradeoffs and
       | balances. We take that sense of taste somewhat for granted in
       | "mainstream" programming styles.
        
       | makerofthings wrote:
       | I have a good 30 years of C/C++ under my belt and have been
       | learning Haskell for the last 4 years. You can write a buggy
       | version of a program in C after spending an afternoon learning
       | it. You can write a bug-free version in haskell but you'll be
       | spending a few weeks worrying about monads. I think C just looks
       | easier because you can learn enough to be dangerous without much
       | effort, getting to a level where you can write reasonably safe C
       | will take a lot longer than getting to that same level in
       | Haskell.
        
         | the_only_law wrote:
         | After trying to join in on the monad jokes for forever, I
         | opened up the the Wikipedia page on Monads (in the functional
         | programming context, not the page in raw category theory) and
         | it actually kinda made sense.
        
           | exdsq wrote:
           | The problem that made monads make sense for me was when I had
           | to chain (err, val) tuples for six or seven functions that
           | only took val and handling the (err, _) bit was awkward.
           | Someone showed how to rewrite it using monads to handle that
           | without the boilerplate and voila.
        
             | javert wrote:
             | If someone would make a tutorial that replicates the
             | process you just described, that might be a good way to
             | teach monads.
        
               | ghayes wrote:
               | I strongly suggest starting with a language like Elm to
               | get into FP, since you start to use `map` and `andThen`
               | quite often, but you also get sick of writing `a |>
               | Result.andThen fn1 |> Result.andThen fn2`. This can help
               | a programmer realize why it might be better to have a
               | concise syntax for this, like:                   myFun :
               | String -> Result String Int         myFun a =
               | do b <- fn1 a               c <- fn2 b
               | return c
               | 
               | That said, I think the other problem with Haskell is the
               | definition of the bind operator: it is not obvious to a
               | beginner which concrete function is actually being called
               | for each monadic operation. Idris2, for instance, lets
               | you specify the bind operator in its do notation[0].
               | 
               | [0] https://idris2.readthedocs.io/en/latest/tutorial/inte
               | rfaces....
        
           | ModernMech wrote:
           | I like the way that "Learn You a Haskell" puts it:
           | "If we have a fancy value and a function that takes a normal
           | value but returns a fancy value, how do we feed that fancy
           | value into the function?"
           | 
           | That's basically all a monad is. If you know what map() does
           | (in Haskell terms, map is a "functor"), then you know what a
           | monad is, as it's just a fancy map().
           | 
           | I'll put it in Rust terms:                 let x: Option<u8>
           | = Some(5);       fn foo(x: u8) -> Option<u8> {...}
           | 
           | How do we apply the function foo to x? That's what monads are
           | for.
        
       | marcodiego wrote:
       | Because you're already used to a very different approach to
       | express the solution to a problem. It is like somebody who
       | already knows an western language trying to suddenly learn
       | Mandarin.
        
         | nowherebeen wrote:
         | I equate it to a skier learning to snowboard. A skier points
         | their toes downhill to go down the mountain; a snowboarder
         | points their toes perpendicular. Once you are used to pointing
         | your toes downhill, its very hard for the mind to switch
         | context to perpendicular because your mind is telling you
         | that's how you stop.
        
         | Jtsummers wrote:
         | Hah, I was pondering how to write a longer comment expressing
         | this same thing so I'll piggyback on yours.
         | 
         | Paradigms are modes of thinking. You can't just pick up a new
         | paradigm on the fly when you've spent your entire life in
         | another one. Some individuals are exceptions, but most of us
         | aren't so lucky as to have such a natural aptitude for changing
         | our minds on the fly.
         | 
         | In order to be introduced to a new paradigm you have a couple
         | options:
         | 
         | 1. Sink or swim. In Haskell, this is the monad tutorial. Why
         | the hell do people start their instruction here? Did _they_
         | start here? If they did, did they _succeed_ from that point or
         | did they have to find another path and just forgot that this
         | was a really stupid way to start?
         | 
         | 2. Baby steps. "See Spot. See Spot run. Run Spot, run!"
         | Learning Italian (previously Spanish), this is literally the
         | level I'm at (actually, a bit better, but still highly
         | constrained by my limited vocabulary). In Haskell, this is:
         | double :: Int -> Int       double x = 2 * x       quadruple ::
         | Int -> Int       quadruple x = double (double x)
         | 
         | Simple functions tested in the REPL. Then you teach them about
         | function composition (drawing on their knowledge from
         | mathematics, where it's the same idea and not merely an
         | analogous idea) and make a point-free version of quadruple.
         | Then you show how functions can be passed around so that you
         | can do:                 square_function f = f . f
         | quadruple = square_function double
         | 
         | Maybe give that first function a better name, my coffee hasn't
         | kicked in yet. My point, though, is that functional programming
         | in Haskell does _not_ rely on monads when _teaching_ the topic.
         | There are a million things to teach before you even reach that
         | point, and only once the student has a foundation in Haskell 's
         | syntax, base semantics, and type system do they need to be
         | introduced to monads. At which point it'll make a lot more
         | sense because they'll be able to grok what monads add to the
         | language.
         | 
         | By analogy (hah!), we don't start C language learners with
         | implementing a generic swap or sort function. That would be way
         | beyond their initial capability, relying no too many ideas that
         | they have no foundation for (that said, it's a shorter path to
         | that in C than monads in Haskell).
         | 
         | So why do people think that learning a totally novel (to them)
         | paradigm like functional programming, especially in the uber-FP
         | language Haskell, can be done by starting at the deep end
         | without studying its fundamentals?
        
       | choeger wrote:
       | Because functional programming is so damned hard if you don't
       | grasp recursion. Otherwise, it is simple.
       | 
       | Sorry for the cheap pun, but I think the main difficulty is
       | getting along with recursion.
       | 
       | And corecursion, of course ;).
        
         | bsaul wrote:
         | recursion is always synonymous to me of unbounded memory usage.
         | Understanding the memory consumption of a for loop updating a
         | local variable looks easy. But a recursive function ? forget
         | it...
        
           | emodendroket wrote:
           | Well that's why you want a function to be tail recursive,
           | right?
        
             | bsaul wrote:
             | yeah but how do i know for sure that the compiler is going
             | to optimize the memory or not ? Some compilers are smarter
             | than other to rewrite recursion in a tail recursive way,
             | and others aren't, and it's probably not possible all the
             | time anyway..
             | 
             | It seems like a very convoluted way to do a simple thing (
             | sometimes).
        
               | carnitine wrote:
               | A tail recursive function can always be optimised into
               | code which does not consume memory on recursion, and it's
               | a pretty basic fact to learn about a given
               | language/implementation.
        
               | c-cube wrote:
               | Functional languages will typically guarantee you that
               | tail recursion is constant space. The exception is
               | languages running on a FP adverse runtime such as the
               | jvm, and they tend to provide a special keyword and
               | rewrite into a loop.
               | 
               | Also, mutual recursion is a bit more general than loops
               | :)
        
               | emodendroket wrote:
               | In Scala, as I recall, you could annotate a method as
               | tail recursive so it wouldn't build if it weren't. A
               | serious functional language pretty much has to have an
               | answer for this since you're supposed to use recursion
               | instead of iteration.
        
               | Twisol wrote:
               | I suspect you think about recursion in terms of a call
               | stack, yes? So when you have tail recursion, you're still
               | pushing a frame onto the stack by default, _unless_ the
               | compiler recognizes that it can optimize that way. Yes?
               | 
               | The traditional FP model of computation doesn't have a
               | call stack. It proceeds by reduction: replace one
               | subexpression with another, in the program text itself,
               | and repeat until you can't do it anymore.
               | 
               | So if I've got a fibonacci function in two clauses, `fib
               | 0 a b = b` and `fib n a b = fib (n - 1) b (a + b)`, then
               | a reduction may look like this:                     fib 3
               | 0 1         -- initial program         = fib 2 1 (0 + 1)
               | -- substitute second clause of `fib`         = fib 2 1 1
               | -- evaluate `+`         = fib 1 1 (1 + 1)         = fib 1
               | 1 2         = fib 0 2 (1 + 2)         = fib 0 2 3
               | = 3                 -- substitute first clause of `fib`
               | 
               | Notice how the tail-recursion naturally falls out of the
               | substitution steps performed by the interpreter. There
               | are no stack frames; the whole "rest of the program"
               | (which is what a call stack _is_ ) is just the program
               | itself.
               | 
               | This isn't just an analogy; this is the way computation
               | works in an FP. To an FP system, the _call stack_ is the
               | invisible, behind-the-scenes optimization.
        
           | asimpletune wrote:
           | They can be made to work very much the same with the
           | compiler. The main difference is tail recursive or not.
           | Basically whether the answer is being accumulated along the
           | way or requires returns from the call stack to accumulate the
           | result.
           | 
           | Otherwise there's no law of computer science making the two
           | very different. Some language compilers implement recursion
           | naively, that's mostly it.
           | 
           | The call stack itself is literally just a stack provided by
           | the OS with restrictions meant to protect the other programs
           | in the os.
        
             | jarcane wrote:
             | Yes. Fundamentally, the problem is cultural, not
             | mathematical. A modern language like Racket with proper
             | recursion optimizations will compile and optimize a
             | recursive solution that is as fast or nearly (and even
             | sometimes faster) than a mutable imperative one.
             | 
             | The problem is that the idea of recursion as slow or
             | resource hungry has become a kind of circular just-so story
             | among imperative programmers and compiler developers who
             | don't want to write recursion optimizations (or don't even
             | know how).
             | 
             | The argument goes that recursion is slow, so don't use
             | recursion, and if you raise the idea of optimizing
             | recursion, the compiler dev dismisses it, because why would
             | you write recursion support, recursion is slow.
             | 
             | Now it's fair to say in an earlier era, this was somewhat
             | justifiable, but the logic has been passed down far longer
             | than it's actually been true of the technology available. I
             | remember reading "recursion bad" in C books in the 90s, and
             | it's _still_ so pervasive that even though TCO has been in
             | the JS standard since ES6 years ago, most browsers still
             | can 't be bothered to support it.
        
         | sltkr wrote:
         | I think recursion is just one of the hurdles.
         | 
         | Another one is the use of higher-level functions and function
         | composition.
         | 
         | Another one is the use of monads (at least in pure functional
         | languages like Haskell).
        
           | nightski wrote:
           | Monads aren't really related to purity. Haskell uses one
           | instance of a monad, the IO monad to encapsulate IO. But
           | there are other ways of doing it. Most monads have nothing to
           | do with side effects.
           | 
           | You see things like functors/monads all the time even in
           | regular imperative languages. For example in .NET we have
           | Linq, Nullable types, etc... They aren't as well defined as
           | in Haskell but still an incredibly useful pattern.
           | 
           | You also have higher ordered functions and whatnot in
           | imperative languages now. In fact, in JavaScript and .NET
           | they are used all over the place.
        
             | DaiPlusPlus wrote:
             | I don't believe .NET's `System.Nullable<T>` is a monad. For
             | example, a type that can encapsulate _any_ other type
             | fulfils the definition of a _monadic-value_ , but
             | `Nullable<T>` cannot be used with reference-types and
             | delegates, only a strict subset of value-types (as
             | `Nullable<T>` itself is a value-type, but you cannot use
             | `Nullable<T2>` for T1 in `Nullable<T1>`).
             | 
             | While .NET allows for composition with delegates, it's not
             | very smart, and results in unnecessary type information
             | erasure; for example in Linq if you take a projection of a
             | fixed-size list, then that length information is lost if
             | you then add another step after the projection. (Linq
             | internally has some ugly, but inconsistent implementation
             | hacks; for example, IList<T> length information may be
             | preserved but IReadOnlyCollection<T> length information
             | will not.
        
               | nightski wrote:
               | C# has nullable reference types now. But I agree it's not
               | perfectly a monad in implementation due to engineering
               | decisions. But the pattern generally follows that of the
               | Option monad in Haskell, even if it falls short. If you
               | know the Option monad you'll find it really easy to pick
               | up .NET's nullable types.
               | 
               | That's my point, you find these patterns all over in
               | common programming languages and even though they are
               | hard to learn it's worth it.
        
               | recursive wrote:
               | It's going the other way that's the problem. I understand
               | .net nullable, including some of the weird edge cases and
               | trivia. None of that seems to provide any illumination
               | into the working of more general monads.
        
               | nightski wrote:
               | Weird, when I was learning Haskell I felt like the Option
               | type looked very familiar. Then when I learned about fmap
               | and bind it was immediately obvious why these would be
               | useful. You mean I can apply a function to a nullable
               | type that has no knolwedge of nullable? Cool! Or I can
               | compose general operations on nullables? That is neat.
               | 
               | In fact I think this was the easiest way for me to learn
               | monads - to learn them in the context of things I already
               | understood.
        
               | DaiPlusPlus wrote:
               | That's because Nullable<T> and nullable-reference-types
               | _aren 't_ monads - precisely because they aren't
               | composable.
               | 
               | I think this SO post covers it well:
               | https://stackoverflow.com/questions/44965/what-is-a-monad
        
             | sltkr wrote:
             | All essential applications of monads in Haskell are there
             | to work around the limitations of purity. The I/O monad, ST
             | monad, State monad, etc.
             | 
             | Yes, I know List and Maybe are also technically monads in
             | Haskell. But you don't need to think of them as monads or
             | even understand monads to do anything useful with them.
             | Applying monad operators to lists and maybes is only
             | occasionally useful.
             | 
             | In most impure functional languages (LISP, ML) you rarely
             | model any data types as monads explicitly. As soon as you
             | have side-effects, they lose their appeal.
        
               | nightski wrote:
               | This is just not true, you throw out some of the most
               | useful monads :)
               | 
               | Also ST and State have no side effects. The only monad in
               | Haskell that has side effects is IO (unless you were to
               | sneak in an unsafePerformIO but that is an entirely
               | different discussion). So they aren't there to work
               | around the limitations of purity, because they are pure.
        
               | sltkr wrote:
               | > This is just not true, you throw out some of the most
               | useful monads :)
               | 
               | Namely?
               | 
               | > Also ST and State have no side effects.
               | 
               | I didn't say they do. I said they are useful only because
               | Haskell doesn't allow side-effects. In ML or Lisp you'd
               | just update a local variable instead.
        
               | nightski wrote:
               | Lists, Option, Either, Reader, Logging (non-effectful),
               | STM etc... There is even a probability monad that I have
               | found quite useful.
               | 
               | ST & State are far more useful than updating a local
               | variable. If you are going to choose the simplest use
               | case for them ever and then say that is the only thing
               | they can do it is not a productive discussion. The state
               | monad is a lot like a context object that allows state to
               | flow through function composition (for functions that
               | have no knowledge of such state). For example you could
               | compose a bunch of functions and have the results of each
               | function call stored without changing any of the
               | functions to know about the operation. It's a method of
               | abstraction and encapsulation.
               | 
               | It's not just monads that are useful either, it is the
               | full hierarchy of Monoids, functors, applicatives,
               | monads, etc...
        
         | nwallin wrote:
         | I disagree entirely.
         | 
         | I understand recursion just fine. I can look at a problem and
         | think "this problem space is correctly represented by a
         | tree/graph" and can meaningfully translate that into a program
         | that shoves the data into a tree/graph-like data structure, and
         | my natural inclination when computing on a tree/graph-like data
         | structure is to use recursion.
         | 
         | On the other hand, I understand that _not all problems_ lend
         | themselves to recursive solutions. I can look at a problem and
         | think  "this problem space is correctly represented by a
         | matrix" and the reality is that linear algebra problems are
         | often iterative, not recursive, in nature. It is certainly
         | possible to do the simplex algorithm recursively with immutable
         | data, but it's just so much straightforward to do it
         | iteratively on a mutable matrix.
         | 
         | The other thing is that most of my day job is just hooking one
         | API up to another API to achieve my business's desired outcome.
         | I don't need "interesting" algorithmic solutions for 95% of
         | what I do. I just... extract data from one API and plug the
         | data into another. You don't need recursion for that, and the
         | "list of steps to do in order and (possibly) loop over that"
         | paradigm with whichever seasonings you wish to add to it is
         | just fine. (OOP is the flavor of the ~~day~~century at my
         | company)
         | 
         | edit: I forgot the bit that ties it all together. I am
         | absolutely no good at functional programming. I've tried to sit
         | down and learn Haskell or Lisp a dozen times and always failed.
         | I've bought books. I'm still no good. It just takes me ten
         | times as much code that's completely unreadable to do something
         | that would be simple and straightforward in C++.
        
         | onlyrealcuzzo wrote:
         | I also think that most people who learn a functional language
         | try to take what they know in an imperative language and
         | translate it on the fly to a functional paradigm.
         | 
         | This seems like a lot more work than just learning how to think
         | functionally.
        
           | TchoBeer wrote:
           | Alternatively, learning a new thing is easier if you have a
           | grounding somewhere. Maybe the ideal would be a guide like
           | "this is how functional programming differe from imperative
           | programming"
        
           | dagw wrote:
           | The intro to programming course for the math department at my
           | University was taught in Haskell. And it was really
           | interesting to see how people who had never programmed before
           | on the whole did better than those who had a bit of
           | programming experience.
           | 
           | Those that had programmed before kept trying to make Haskell
           | behave how they thought a programming language 'should'
           | behave, while those who had never programmed just looked at
           | Haskell and went "I guess this is what programming is" and
           | just rolled with it.
           | 
           | The only problem was that once they moved onto the
           | intermediate course, taught in Java, they where completely
           | lost again.
        
             | scns wrote:
             | Introduction to Programming at CMU is done in SML. They
             | make the same observations as you. Those that have prior
             | exposure to programming struggle. Those students without
             | experience find it easy. They are a bit baffled in the next
             | course, which is done in an imperative language.
        
               | rgrmrts wrote:
               | 15-150 (during my time), but it wasn't the intro to
               | programming - the course is titled "introduction to
               | functional programming". The intro to programming is
               | Python (unless it changed).
               | 
               | The trajectory for students is Python to C to SML (15-110
               | to 15-122 to 15-150). Some people take the C and SML
               | courses in the same semester.
               | 
               | I was really happy to have been introduced to many
               | different paradigms over the course of a few years. But
               | to both your points, once we moved on to Java I had a
               | really bad time.
        
         | Banana699 wrote:
         | > I think the main difficulty is getting along with recursion
         | 
         | meh, recursion is easy. Recursion is mainstream. It _began_ as
         | a way to fake a loop without mutation, but I struggle now to
         | remember a mainstream language without it.
         | 
         | The hardest part is all the new patterns you have to grok, it's
         | like learning programming again from a blank slate, because it
         | kinda is. It doesn't get any easier when Haskell decides it
         | needs 7 new syntaxes and someone rushes to compose them all in
         | one line.
        
       | jghn wrote:
       | Most people are taught from day 1 to code in some combo of
       | imperative and OOP styles.
       | 
       | The issue is not that FP is hard to learn. The issue is that most
       | people start off from a much lower baseline knowledge-wise than
       | they will when learning a new imperative and/or OOP language,
       | framework, etc.
        
         | moralestapia wrote:
         | I was going to comment on a similar line.
         | 
         | I come from the OOP school and have done 10s-100s(?) of C/C++
         | projects, which I like, btw. But when I discovered FP it was an
         | eye opener, the breadth of things that became
         | possible/tractable is great, even my OOP programs became much
         | better because of it.
         | 
         | I think that the OOP curriculum is actually a regression, and
         | would recommend anyone who is just starting out to try out FP
         | first.
        
           | eightysixfour wrote:
           | As someone who only dabbles in code, I'm very interested in
           | starting FP first, but I find that the beginner tutorials
           | mostly assume previous programming knowledge/skills, and the
           | communities aren't really geared towards folks who don't have
           | backgrounds from other areas.
           | 
           | It is certainly possible I'm not looking in the right place
           | for the right thing, but it should probably be an area of
           | improvement for those communities in the future IMO.
        
             | Twisol wrote:
             | You might like "How to Design Programs": http://htdp.org/
             | 
             | It appears to exclusively work with the usual FP
             | understanding of computation as _reduction_ (simplification
             | of an expression), avoiding all named mutable state. This
             | is (in my opinion) the most important and fundamental
             | difference between functional and imperative, and is
             | something you miss if you try to learn FP in, say,
             | JavaScript.
             | 
             | It also doesn't seem to assume any prior experience with
             | programming. The last chapter even has a section
             | specifically directed at students who aren't computer
             | scientists or software developers.
        
             | blagovest wrote:
             | Hey! I am writing an ebook about high-level programming
             | concepts that starts off with a FP view point and builds on
             | top of it. If that sounds interesting, I'd love to share (I
             | am eventually going to sell it but I am fine giving away
             | drafts)
        
               | eightysixfour wrote:
               | Absolutely, would love to take a look.
        
         | donglover69 wrote:
         | Exactly. I came from a math background and only ever used
         | Wolfram Mathematica for programming, and naturally used
         | functional programming. Later on I tried to learn imperative
         | programming and it boggled my mind. The idea of changing a
         | state over and over seemed so janky to me.
        
       | CalChris wrote:
       | Some people, when confronted with a problem, think "I know, I'll
       | use regular expressions." Now they have two problems.
       | 
       | That isn't even a criticism of regular expressions nor is this a
       | criticism of functional programming. It's more about that
       | fashionista need to use something rather than solve something.
        
       | dtagames wrote:
       | I had a chance to speak with John Backus when I worked at IBM
       | where he invented functional programming with the goal of
       | removing some of the spaghetti and incomprehensibility of
       | imperative and procedural code. It certainly was _not_ an
       | immediate hit!
       | 
       | Despite being an IBM Fellow (the company's highest rank with
       | complete freedom to work on whatever you want), John was having
       | trouble getting any traction for his ideas. I certainly didn't
       | grok it at the time. I couldn't see the utility over the
       | procedural PL/AS and imperative assembler we were already using
       | to create the mainframe's higher-level language compilers.
       | 
       | I've since become a big believer in the functional style, sadly
       | after John's passing. It's certainly not the solution for
       | everything. Even the lambda calculus requires that you feed it a
       | starting series of "magical" integers to work. But functional
       | _is_ a useful way of thinking about programming, especially for
       | library functions.
       | 
       | I would say the key difference between the functional style and
       | imperative/procedural is not the presence of recursion but the
       | lack of _state_. A functional function cannot have any internal
       | state store, nor rely on anyone else having one. In other words,
       | all of its arguments and values must be fully defined by
       | parameters. This is a super-critical concept in debugging because
       | it helps bulletproof your function.
       | 
       | Having said that, no real working program can be fully
       | bulletproofed with the functional style because we need to hold
       | onto state in real programs. (Is the user logged in?, etc.) We
       | cannot pass these values in every single time and have a
       | practical program.
       | 
       | I think merging these concepts of functional when you can and
       | state when you must is the easiest approach. Certainly there are
       | many functions in every program which are functional in style in
       | that they do not contain or rely on any state, and those are good
       | jumping-off points for starting to understand the functional
       | style.
        
         | emodendroket wrote:
         | Of course a program without side effects is useless, but the
         | idea is deferring those as much as possible, isn't it?
        
           | carnitine wrote:
           | No, a program without effects is useless. Side effects, i.e.
           | some action done _on the side_ while evaluating the program
           | are not required. There are other ways to treat effects in
           | programs, particularly as values.
        
             | emodendroket wrote:
             | Unless you display them, save them, send them somewhere,
             | etc, they're useless. Therefore, a program without side
             | effects is useless.
        
               | carnitine wrote:
               | Effects, yes. Side effects are a particular form of
               | effect. A pure functional language can compose an
               | effectful value that is interpreted by a runtime, but no
               | effect happens on the side as the program is evaluated.
        
               | emodendroket wrote:
               | That's not really what side effects mean in programming: 
               | https://en.wikipedia.org/wiki/Side_effect_(computer_scien
               | ce)
               | 
               | > In computer science, an operation, function or
               | expression is said to have a side effect if it modifies
               | some state variable value(s) outside its local
               | environment, that is to say has an observable effect
               | besides returning a value (the intended effect) to the
               | invoker of the operation.
        
               | ratww wrote:
               | GP is correct. There are _zero_ side-effects _inside_ a
               | pure program. All the side-effects happen outside it, in
               | a  "runtime" (a better name IMO is "imperative shell")
               | that exists totally separate from the program. The main()
               | function of a pure program executes completely and
               | terminates before any side effect has a chance to happen.
               | 
               | I put quotes around runtime because it's not a runtime
               | like an interpreter in dynamic languages, or a library
               | that you can call from inside your pure program. This
               | runtime just calls your _main()_ function, which return a
               | complex value (it 's a chain of lambdas, to spoil it)
               | that is interpreted by this runtime or "imperative
               | shell".
               | 
               | I understand this sounds unintuitive and might seem very
               | confusing, but this is what makes useful pure programs
               | possible. These couple presentations show how this type
               | of boundary between imperative and functional code works
               | with simpler type of program [1]. The only difference is
               | that Haskell's "imperative shell" is lower-level than the
               | presenter's. It only deals with IO, etc, whereas the
               | presenter's imperative shell also has some domain code.
               | 
               | [1] https://www.destroyallsoftware.com/talks/boundaries /
               | https://www.destroyallsoftware.com/screencasts/catalog/fu
               | nct...
        
           | dtagames wrote:
           | Yes! JS and TS allow this kind of functional style which I
           | try to adhere to. There must be state, of course, but as few
           | functions as possible should rely on it and certainly _no_
           | function should  "reach" into anywhere else to get a value.
           | Those things have to be passed-in.
           | 
           | The change from AngularJS to Lit (or React), is an example of
           | this kind of functional refactoring. AngularJS had two-way
           | databinding (state!) and it attempted to pass that state
           | upward when things changed. This made horrible spaghetti and
           | impractical large apps.
           | 
           | Lit and React are only top-down. Yes, each component has
           | state but only at the top. It gets passed-in as a parameter
           | to other things, but they can't change it in return. This is
           | much more modular and debuggable.
        
             | neolefty wrote:
             | Yup, React is all functional these days, and pretty
             | widespread. My team, for example, is "discovering" the
             | benefits of functional approaches, and it's nice that it's
             | a gentle slope.
        
               | recursive wrote:
               | Use of state is still widespread. `useState` is a
               | function in the javascript-specification sense, but not
               | in the FP sense, since its only purpose is a side effect,
               | not the return value. I don't think react can do anything
               | useful if you use only FP constructs.
        
               | ratww wrote:
               | It would be possible have a purely functional React if 1)
               | the current state of the component were injected via an
               | argument, and 2) instead of a _setState_ call we just
               | returned the state changes we needed.
               | 
               | With that our code would be 100% pure, and all the side-
               | effect part would live outside our JSX files, similar to
               | how Haskell does.
        
             | emodendroket wrote:
             | The biggest downside with doing it in something like JS is
             | you don't have the same under-the-hood optimizations. In
             | functional languages it's not actually going to allocate a
             | whole new array each time an immutable list is appended to,
             | but that's exactly what will happen in JavaScript. But yes
             | I agree, these concepts are showing up everywhere, even if
             | you don't do "FP."
        
               | pyrale wrote:
               | > In functional languages it's not actually going to
               | allocate a whole new array each time an immutable list is
               | appended to, but that's exactly what will happen in
               | JavaScript.
               | 
               | Efficiency depends on how your js runtime is optimized.
               | Elm works fine, for instance.
        
       | GnarfGnarf wrote:
       | I lost interest in FP when my FP solution for the Fibonacci
       | series was exactly how _not_ to do it.
        
         | Twisol wrote:
         | For completeness, what was your solution? I promise not to
         | judge it if you don't want me to :) but it seems like it would
         | be a valuable discussion for others who might be on the fence.
         | 
         | My solution (from another conversation on this very page) is:
         | fib 0 a b = b         fib n a b = fib (n - 1) b (a + b)
         | 
         | It might (or might not) look simple, but this solution arises
         | from an understanding of computation as reduction, which is
         | very much not how imperative languages go about things. So it's
         | really not shameful or even problematic to have arrived at a
         | different solution first.
        
         | toast0 wrote:
         | You can write the closed form in FP just as well as any other
         | language.
         | 
         | Most FP languages will let you write a recursive form that
         | won't blow the stack. In C, you'd need to used closed form or a
         | loop if you value your stack.
        
       | emodendroket wrote:
       | Well, as alluded to, mostly because it requires you to start over
       | and relearn basic things. But the compiler devs for your language
       | specifically setting out to break your program is an unusual
       | hurdle. Based on that alone I would never touch Elm.
        
         | splintercell wrote:
         | It's that attitude which makes elm, an excellent programming
         | language to learn function programming on.
        
           | emodendroket wrote:
           | Maybe it's great for learning, but many of us wish to deliver
           | a useful project and not just do something for purely
           | didactic purposes
        
           | macintux wrote:
           | Which would be fine if the creators didn't also push for Elm
           | to be used for production use, which is clearly a dubious
           | proposition.
        
       | bob1029 wrote:
       | I have found that my best use of functional programming occurs
       | within hybrid systems.
       | 
       | When you can use either technology on a per-function or class
       | basis, it really helps with adoption. Languages like C#8+ almost
       | feel like cheating when it comes to mixing ideologies. Some
       | developers think this sucks, but I view these complaints similar
       | to those who would complain that someone might try to use a
       | hammer to install a screw.
       | 
       | The general theme in my mind is to use the imperative code to
       | construct the walls of the functional matrix wherein I author the
       | actual business logic as pure functions.
       | 
       | FP for me is usually in the form of SQL, LINQ or switch
       | expressions. I personally have never wanted to go all the way
       | with FP. I see how you can do it in theory, but I question the
       | practical engineering value of actually pursuing this. The most
       | important & scary parts of our product are within this "hosted"
       | functional scope.
        
       | myWindoonn wrote:
       | Good post from somebody with an overflowing teacup. Haskell's not
       | magic or special; it's Just Another Programming Language, really.
       | Reading their monad tutorial
       | (https://gist.github.com/cscalfani/b63552922a8deb2656ecd5ec8a...)
       | it doesn't sound like they actually understand monads; they don't
       | know about algebraic laws or the join operation.
        
       | zelienople wrote:
       | Why is learning anything so damned hard?
       | 
       | Mainly because we are monkeys to whom a reasonably accurate
       | reductive analysis can be applied if we label the axes "asshole"
       | and "idiot".
       | 
       | It was a good blog post by a reasonably intelligent monkey who
       | seemed to score low on the "idiot" axis. But some other monkey
       | pegged the "asshole" axis by preventing us from highlighting the
       | text so we could right-click and search to answer the primary
       | question, "What is it?"
       | 
       | Namely, what is functional programming? Even after besting the
       | right-click hurdle, no one easy and succinct answer is available.
       | 
       | The meta-analysis of this blog post therefore circles back around
       | to perform a second-phase adjustment of the author's "idiot"
       | score once we realize that he has done exactly what he is
       | complaining about; he is a bad teacher because he did not answer
       | the "What is it?" question.
       | 
       | He seems like a reasonably nice person, so I think we have to
       | leave his "asshole" score alone in the second phase.
       | 
       | The collective effort, however, scores high on both the "idiot"
       | and "asshole" axes, and this is the core of the "bad teacher"
       | problem.
       | 
       | I spent most of my long university career angry about this
       | problem. Why is is that monkeys can't teach?
       | 
       | Partly, it is because they are arrogant assholes who don't want
       | to weaken their position by making it easy for others to access
       | their expertise.
       | 
       | And partly it is because they are monkeys who think more highly
       | of themselves than is justified, and therefore they cover their
       | ignorance with jargon, hand-waving, and obfuscation.
       | 
       | Other than extinction, I'm not sure how to solve the problem, but
       | I'm sure that the first step is by starting every lesson by
       | answering the "What is it?" question succinctly and concretely,
       | and, more importantly, realizing that if you can't do that, you
       | should shut the fuck up and go away.
        
         | btkramer9 wrote:
         | To your point about others not teaching well to preserve their
         | status, I'm sure it exists but not that prevalent. I think
         | people who have known something for a long time just forget how
         | to empathize with not understanding what they've known for so
         | long.
         | 
         | For this reason alone I think this is why fellow students tend
         | to be much better at tutoring/helping each other instead of
         | their professors.
        
         | scns wrote:
         | The experts blind spot comes to mind:
         | 
         | https://thevaluable.dev/expert-blind-spot-software-developme...
         | 
         | https://nscblog.com/continual-learning/understanding-underst...
         | 
         | Dropping the judgements, assuming positive intent and trying to
         | see the situation might help.
        
       | TheRealNGenius wrote:
       | It's really not
        
       | Fiahil wrote:
       | Functional Programing is hard to learn because it literally
       | changes the neural pathways in your brain. Once you learn it,
       | there is no going back : your grey matter will be changed
       | forever.
       | 
       | I used it a lot in the past, and less nowadays (Rust), but I
       | occasionally have to teach my coworkers on basic FP principles so
       | they can use and write good Python code. Simple descriptions make
       | the learning more palatable and doesn't scare people ("you could
       | use a Monoid here" -> "Try using a class like this, with an
       | `empty` and `combine` function, here").
       | 
       | It usually takes about 6 months of daily practice to learn basic
       | FP skills and 1-2 years to go from beginner to "intermediate"
       | level. Occasionally, you might encounter a FP grandmaster who
       | will melt your brain in less than 2 minutes of conversation, some
       | things never change.
        
         | dtagames wrote:
         | So true! It's a tough disease to catch but totally incurable.
         | 
         | Once you have the bug, you start to pick-up _code smell_ in
         | anything that isn 't functional. You see code and ask, "Why are
         | we touching that?, Why are we holding onto this?" Being able to
         | think in a functional style encourages you to throw away as
         | much code as possible and hang-on to as few crufty elements of
         | state as are minimally required.
         | 
         | It also makes you very anti-OOPS and hesitant to define
         | "classes," since these violate the first principles of
         | functional.
        
       | dingosity wrote:
       | Shouldn't this article have been titled "Why Is Learning Haskell
       | So Damn'd Hard?"
       | 
       | Don't get me wrong. I like Haskell. But yeah, I learned Haskell
       | because I used to sit at a desk across from Brian O'Sullivan (who
       | later wrote "Real World Haskell".) And even having Brian around
       | to answer questions, it still required stretching of the
       | brainpan. But at least I had a guide.
        
       | pjmlp wrote:
       | It is really?
       | 
       | Personally I think it is a matter of what teacher one happens to
       | bump into.
       | 
       | I was quite lucky to have such set of teachers for logic
       | programming (Tarsis World and Prolog), and Functional Programming
       | (Lisp, Miranda, Caml Light).
       | 
       | It felt no different form other programming classes.
       | 
       | In fact, it had higher success grades than thermodynamics,
       | electromagnetism physics or the most feared of all assignments,
       | data structures and algorithms.
       | 
       | So dammed hard depends very much on the learning path.
        
       | jasperry wrote:
       | I love functional programming and I think every CS major should
       | learn the key concepts of it: higher-order functions,
       | immutability, purity, and how they can lead to better designs and
       | more reliable software.
       | 
       | However, I believe that even after the learning curve has been
       | scaled, the task of writing code in functional languages is
       | objectively more difficult in at least one way: Coding a function
       | in the expression-oriented syntax of functional languages has a
       | higher cognitive load than coding that same computation as a
       | sequence of statements. You simply have to hold more things in
       | your head.
        
         | matheusmoreira wrote:
         | > higher-order functions, immutability, purity
         | 
         | These concepts aren't hard to understand and are actually
         | incredibly useful. At some point though things get so abstract
         | it's really difficult to understand what's going on. I've seen
         | Haskell libraries that do things I can't explain for reasons I
         | don't understand and the extremely detailed README with
         | diagrams and arrows and everything somehow made it even more
         | complex.
        
           | Twisol wrote:
           | > At some point though things get so abstract it's really
           | difficult to understand what's going on.
           | 
           | A lot of that comes down to extremely advanced use of
           | Haskell's type system. Advanced type systems are valuable,
           | and they're easier to add to FP languages, but I wouldn't
           | consider them to be a fundamentally FP concept. (We see very
           | expressive type systems being included in imperative
           | languages like Rust and Swift these days.)
           | 
           | I think it's useful to keep in mind that Haskell is used a
           | lot for research. You don't see Java used as a research
           | sandbox in the same way, so you're not likely to run into run
           | into these kinds of libraries in Java. (Though, as an aside,
           | I consider anything that heavily uses reflection in Java to
           | be nearly as inscrutable.) It's actually impressive just how
           | many of these research-level libraries are practically useful
           | in some way, even if the bar to understanding them is higher.
           | 
           | I don't think it's a universal truth that libraries making
           | advanced use of type systems must be difficult to understand.
           | Taking the `lens` library as an example (and I think you were
           | alluding to it, anyway), there's a fairly long-running thread
           | of research around what a "lens" even is, and how they fit
           | into a broader domain of "optics". The `lens` library was
           | created based on one particular representation of lenses, and
           | the community tried to find ways to unify the various kinds
           | of optics in a way that made sense to them. I think the more
           | recent understanding of "profunctor optics" might give us a
           | more accessible route to understanding optics in general,
           | separate from the whole hierarchy of distinct optics you can
           | derive from it.
        
       | thysultan wrote:
       | It's not functional programming, it's functional languages that
       | go bat shit crazy with the amount of symbols they use that'd make
       | looking at heliographs a refreshing pass time.
        
         | Jtsummers wrote:
         | Out of curiosity, what are the crazy amounts of symbols present
         | in, say, Erlang, SML, Scheme, or Common Lisp?
        
           | bigbillheck wrote:
           | Parentheses count as symbols.
        
             | Jtsummers wrote:
             | Are there crazy amounts of them? Compared to mainstream
             | programming languages?
        
           | throwaway81523 wrote:
           | We're talking about typed FP so only SML in your list really
           | counts. So let's see: functors, polymorphism, higher-kinded
           | types (does SML have those?), Hindley-Milner type inference,
           | etc. Then for Haskell (the main topic of the linked article),
           | bring in a bunch of unfamiliar algebra such as the notorious
           | monoid on the category of endofunctors. It is actually worth
           | understanding that. I liked this article (prerequisite: some
           | exposure to Haskell):
           | 
           | https://www.haskellforall.com/2012/08/the-category-design-
           | pa...
           | 
           | This is also good:
           | 
           | https://en.wikibooks.org/wiki/Haskell/Category_theory
        
             | Jtsummers wrote:
             | > We're talking about typed FP so only SML in your list
             | really counts.
             | 
             | I like your sense of humor.
             | 
             | Appeal to Wikipedia Fallacy:
             | https://en.wikipedia.org/wiki/Functional_programming
             | 
             | LISP certainly shows up in the discussion. It's even called
             | the _first_ functional programming language!
        
               | throwaway81523 wrote:
               | There's not really an official definition of FP. There
               | are some proposed ones that involve types and some that
               | don't involve them. Mainly though, this is a thread about
               | the linked article, which is about the tribulations that
               | the author had learning Haskell. Most of those
               | tribulations were with the type system and I think that
               | matches most people's experience. You can't transplant it
               | to Lisp.
        
           | codr7 wrote:
           | Common Lisp is about as functional as modern C++, it's a
           | multi paradigm language by design.
        
         | the_only_law wrote:
         | Not only symbols, I've stayed away from Scala because half the
         | libraries I've looked at seem to want to make their own little
         | DSL the language.
        
           | erik_seaberg wrote:
           | That's the way we ought to be working. If you don't write the
           | DSL, you'll have to macro-expand the DSL in your head and
           | write a bunch of boilerplate which everyone will be forced to
           | try to reread and maintain forever.
        
       | nephanth wrote:
       | Imho, ocaml is a way better language than Haskell when you are
       | learning FP coming from other paradigms: it doesn't require you
       | to learn mathematical constructs such as monads or monoids when
       | you are beginning, it allows you to use imperative or OO
       | constructs (though they are discouraged by the language)... When
       | you are used to FP, though, more abstraction can be nicer
        
       | PragmaticPulp wrote:
       | This article is a good example of why I don't use uncommon
       | programming languages for actual projects. I watched an Elm-based
       | project steadily slip behind schedule while the team _insisted_
       | that Elm and FP were actually going to save us a lot of time...
       | eventually some day.
       | 
       | These uncommon FP frameworks and languages can be good tools in
       | the right, experienced hands. They can also be fun for side
       | projects and as learning exercises. But every time I've watched
       | programmers try to use uncommon functional languages for real
       | projects they end up like this article:
       | 
       | > More accurately, learning Functional Programming concepts used
       | in Haskell in 3 months after having thrown out 30,000 lines of
       | code on a project that was now monumentally behind schedule was
       | the hardest thing I had to do in my career.
       | 
       | When you've reached the point of being severely behind schedule,
       | throwing out mountains of code along the way, and struggling
       | mightily just to get basic things accomplished: It's time to
       | stop. Don't double down on a _new_ language that you also have to
       | learn from scratch. Pick something tried and true and get the
       | work done. Revisit the functional language at a later time for an
       | unimportant project or a side project, not something with a
       | deadline.
       | 
       | If the programming language or ideology has become more important
       | than shipping the project, we've lost the point.
        
         | cerved wrote:
         | I wouldn't say the used an uncommon language. They build some
         | kind of tool to run on top of Elm which wasn't inline with the
         | goals of the Elm project (unlcear how). Seems like something
         | that should've been investigated before commiting
        
           | emodendroket wrote:
           | It is inevitable that someone will use a language in the way
           | the developers didn't intend, but this is the only time I've
           | heard of the developers specifically setting out to break
           | their language for some users.
        
             | cerved wrote:
             | that seems to be the angle presented by the author but that
             | doesn't mean that is what happened
        
               | alisonkisk wrote:
               | Elm author is quite vocal about wanting people to only be
               | able to do things one way. It's the reason people choose
               | Elm.
        
         | roenxi wrote:
         | Also the basic pitch of functional programming is "we have
         | better abstractions, you'll write better code". The basic pitch
         | of something like Java is "everyone knows how to get things
         | done in Java" and of Python "there is a right way to get the
         | task done, and we will tell you what that way is".
         | 
         | There is a fundamental mindset here that the Functional
         | languages aren't task-first. Not in the languages, mind, it is
         | in the community. And the tasks themselves can be so simple
         | once the abstractions are under control that people don't write
         | tutorials about the task.
         | 
         | It is visible in this article - the Haskell community is trying
         | to convince this guy that he needs to know a wall of jargon
         | from a relatively obscure branch of maths in order to program
         | effectively. They may or may not be correct, but it is going to
         | be a while before his attention makes it to the task at hand.
        
           | PragmaticPulp wrote:
           | > It is visible in this article - the Haskell community is
           | trying to convince this guy that he needs to know a wall of
           | jargon from a relatively obscure branch of maths in order to
           | program effectively. They may or may not be correct, but it
           | is going to be a while before his attention makes it to the
           | task at hand.
           | 
           | This seems to be the core problem in the communities, like
           | you said: a tendency to believe that time spent learning the
           | language or learning concepts or fighting with libraries or
           | struggling with documentation doesn't actually "count"
           | towards time spent getting the job done.
           | 
           | I think this plays into our tendency to view learning and
           | education as investments rather than costs. That may be true
           | on a personal level when using your own time, but using your
           | employer's time to experiment with difficult new concepts and
           | languages when you have a deadline approaching (or long since
           | past) is not cool.
        
             | laserlight wrote:
             | > using your employer's time to experiment with difficult
             | new concepts and languages when you have a deadline
             | approaching (or long since past) is not cool.
             | 
             | To defend the counterpoint, artificial scarcity is abundant
             | in the industry. Deadlines always approach, projects are
             | already late. If employees don't learn and improve on the
             | job, employers will be happy to replace them.
        
             | whateveracct wrote:
             | > using your employer's time to experiment with difficult
             | new concepts and languages when you have a deadline
             | approaching (or long since past) is not cool.
             | 
             | It's in fact very cool. I get to take those skills with me
             | when I leave in a few years :)
        
             | Terretta wrote:
             | > _using your employer's time to experiment with difficult
             | new concepts and languages when you have a deadline
             | approaching (or long since past) is not cool._
             | 
             | As kindly as I can put it: I'd argue that within this
             | sentiment are the foundations of everything wrong with the
             | ecosystem of professional software engineering.
             | 
             | Let's start with, if you don't let people learn on the job,
             | you have to have at least 20% annual turnover to be only 5
             | years behind the knowledge curve.
             | 
             | At 10% turnover, you're 10 years behind. Managers think
             | people shouldn't be learning on company time, HR tells the
             | board lower turnover is a goal.
             | 
             | Inevitable next step is pausing _all_ productive work to
             | undertake a "Digital Transformation(tm)" to try to replace
             | 20 years of old tech. But the firm won't know how.
        
               | IncRnd wrote:
               | >> using your employer's time to experiment with
               | difficult new concepts and languages when you have a
               | deadline approaching (or long since past) is not cool.
               | 
               | > As kindly as I can put it: I'd argue that within this
               | sentiment are the foundations of everything wrong with
               | the ecosystem of professional software engineering.
               | 
               | Almost all Software Engineering, as practiced, is not a
               | form of engineering in any way. Many times Software
               | Engineering is really a bunch of commodity workers, who
               | are learning, assembling commodity components that don't
               | really work, under the oversight of a more senior
               | developer who helps everything not fall apart.
        
               | Twisol wrote:
               | You might be interested to read Hillel Wayne's crossover
               | project, where he interviewed a number of people who had
               | worked in traditional engineering roles as well as in
               | software development.
               | 
               | https://www.hillelwayne.com/post/are-we-really-engineers/
               | 
               | The upshot is that "engineering" isn't the paragon of
               | excellence we like to think it is. Whether or not you
               | agree, it's a good read!
        
               | IncRnd wrote:
               | Thanks!
        
             | AlexCoventry wrote:
             | I think this problem is specific to the Haskell community.
             | No one's going to tell a brand-new Clojurist that they need
             | to learn about reducers.
        
               | cutler wrote:
               | Agreed. Clojure is the most productive language I've ever
               | used.
        
         | emodendroket wrote:
         | I'll say this though: functional techniques really can save a
         | lot of time. I'm not sure I'd recommend Scala for a new project
         | if you don't have Scala experts already, but I apply ideas I
         | got from my experience using it to projects all the time.
        
           | isbvhodnvemrwvn wrote:
           | The question then is whether it was functional programming
           | that actually made the difference, or the people who had
           | enough perseverance and skill to actually learn Scala in the
           | first place running the project.
           | 
           | I've found that people who go out of their way to learn
           | things like that would be more productive regardless of the
           | language itself.
        
             | dgb23 wrote:
             | That's certainly a big part. The other one is less obvious,
             | but is one that shines through this article as well. Once
             | you learned a functional language or any language that is
             | well designed (for me that typically incorporates
             | functional and possibly logic and relational paradigms)
             | then you'll be more confident and productive than before
             | and will have a hard time to justify using a tool that is
             | inferior other than adherence to the lowest common
             | denominator.
             | 
             | I'm sure this can be observed with any profession. A good
             | cook can work with a cheap knife and mediocre ingredients,
             | but give them a nice set of professional kitchen tools and
             | fresh, tasty vegetables and they will happily cook you a
             | meal that makes your evening.
        
             | invalidOrTaken wrote:
             | >The question then is whether it was functional programming
             | that actually made the difference, or the people who had
             | enough perseverance and skill to actually learn Scala in
             | the first place running the project.
             | 
             | Oof, it may indeed be the second, but what do _they_ get
             | out of the deal?
             | 
             | A lot of FP programmers _refuse to go back_ , simply
             | because it feels _nicer_.
             | 
             | It's a hell of a lot easier to "persevere" on a project
             | when your language doesn't make you want to dig your eyes
             | out with a spoon.
        
               | isbvhodnvemrwvn wrote:
               | I agree, but then you should focus on hiring people with
               | these specific predispositions, and not trying to teach
               | your developers FP from scratch.
        
               | pjmlp wrote:
               | Depends on the project, that is exactly what feels to me
               | sbt or scalaz.
        
             | chii wrote:
             | a good language would allow you to express thoughts that
             | are difficult in another language. But this presumes that
             | you have those thoughts to express in the first place. If
             | you don't, the language isn't gonna magically be able to
             | give you the ability to have those thoughts.
             | 
             | So learning functional languages is both learning the
             | language, but to also improve your cognitive capabilities
             | to have more thoughts.
        
             | emodendroket wrote:
             | Well, the ideas I liked, stuff like deferring side effects
             | and avoiding state, were functional ideas. You see a lot of
             | functional concepts and constructs bleeding out into
             | mainstream languages (just look at the last few C#
             | releases, for instance, which look like a list of features
             | borrowed from Scala), which I think will be their legacy
             | more than widespread adoption.
        
         | wyager wrote:
         | FP is absolutely way more time-efficient for most kinds of
         | projects, _if you know what you're doing_. Switching without
         | having sufficient background first is probably not a good idea
         | though.
        
           | taeric wrote:
           | This somewhat annoys me. "Knowing what you are doing" is time
           | efficient. Regardless of what tooling you have.
        
             | brightball wrote:
             | The flip side is maintainability, which gets much simpler
             | long term with FP.
        
               | taeric wrote:
               | Do you have evidence showing this? The few long term
               | maintained programs I am aware of are decidedly not what
               | one would call modern functional.
               | 
               | (Granted, the most ported and maintained software I know
               | of is either Linux or SCUMM.)
        
               | hvs wrote:
               | This is a statement that requires some sort of citation.
               | Extraordinary claims and all that.
        
             | wyager wrote:
             | I know what I'm doing in many languages, and I'm uniformly
             | more productive with the FP ones. The only time I'll reach
             | for a non-FP language is if I'm forced to for work or if
             | I'm working on an embedded system with no allocator.
        
               | taeric wrote:
               | Is this confirmation/survivor bias, though?
               | 
               | I would love to know that there is a panacea that
               | automatically improves productivity. Unfortunately, I
               | haven't seen one in my career, as yet.
               | 
               | I am certainly more happy in many functional languages.
               | And I can see happiness contributing to some. But I can't
               | count that as data, without RCTs or something similar.
               | 
               | I'm not going to go so far as to claim that computer
               | science isn't science. But I do fear that there are more
               | claims than there are checks in our industry.
        
               | wyager wrote:
               | I wouldn't say it "automatically improves productivity" -
               | I suspect it might be limited to more intelligent and/or
               | mathematically inclined programmers. That said, I think
               | for many programmers not using it is a huge and pointless
               | missed opportunity. This is one of those visibly high-
               | return arbitrages that it pains me to see go unexploited.
        
               | taeric wrote:
               | I certainly don't want my criticism to be a call to avoid
               | functional programming. I just get an uneasy feeling when
               | I see it over sold, as well.
        
           | alisonkisk wrote:
           | "knowing what you're doing" is extremely hard in FP, as per
           | the experience of many many productive imperative/OO
           | programmers who tried.
        
           | bsder wrote:
           | > FP is absolutely way more time-efficient for most kinds of
           | projects
           | 
           | I absolutely do not agree.
           | 
           | FP binds your _particular_ choice of implementation to the
           | code architecture. FP actually makes refactoring in the small
           | trivial and refactoring in the large _ferociously_ difficult.
           | 
           | A good example would be a program that runs fine suddenly now
           | needs a "timeout" on an operation. FP implementations now
           | need to thread the notion of time from somewhere near the top
           | of the implementation the whole way down the chain to the
           | function that needs "time".
           | 
           | This is painful.
           | 
           | An imperative programmer throws in a global time variable,
           | possibly a local timeout variable and gets on with life.
           | 
           | Now, if I'm trying to manage a high-complexity codebase, I
           | will probably eat the FP penalty. Having complete
           | determinism, decoupling, and visibility in, say, a network
           | stack makes debugging possible that will be very difficult
           | with sorta-state smeared across a bunch of variables at
           | various level of hierarchy.
           | 
           | However, I accept and acknowledge that I am making a
           | tradeoff.
        
           | Jare wrote:
           | That's the problem with "uncommon": how do you obtain that
           | background and how do you learn what you're doing? (of
           | course, not just you - you, the entire team, and future
           | hires)
        
             | throwaway81523 wrote:
             | The same way you learn anything else that is difficult:
             | time and practice, and start with fundamentals. You can't
             | put it on any work-related critical path until you have it
             | down solid.
        
               | Jare wrote:
               | I mean in the context of an existing company / team of
               | nontrivial size. Most cases I know of, the uncommon
               | language was there from the days of it being a personal
               | or 1-person project. For other types of tech (e.g.
               | infrastructure) sometimes the new/different capabilities
               | are such a defining feature that the lack of familiarity
               | is not as scary. But in programming languages, you can
               | fundamentally do pretty much anything in existing and
               | well known ones.
        
               | throwaway81523 wrote:
               | Have fun writing a web app in assembly language ;). Yes
               | it's been done, but not often, and for good reason.
               | Haskell is sort of a special case: it's best suited for
               | writing compilers, but has been pressed into just about
               | everything else because people are into it for its own
               | sake.
               | 
               | Yes if you're running a C++ shop and someone leaves
               | behind a small program in Haskell, you're probably better
               | off reimplementing it than becoming or hiring a Haskell
               | guru just to maintain that thing. That's a question of
               | _whether_ to learn Haskell, not how to learn it. In the
               | case of the linked article, the author was the one who
               | decided to get the company involved with FP, and gave his
               | thoughts on whether it was worth it.
               | 
               | I can certainly support the idea that someone juggling
               | all the plates required to keep a company running, has no
               | time to embark on a deep and nerdy self-education project
               | in something as abstruse as FP. Better to keep it at the
               | level of a side interest or hobby until you're
               | comfortable with it, before even thinking of doing
               | anything important with it.
        
             | whateveracct wrote:
             | a good attitude and some elbow grease
             | 
             | most "failed" FP projects I've seen mostly lack the former
             | - often due to managers or engineers that come on the
             | project after it first hits prod
             | 
             | then comes the rewrite to add a notch in said managers' and
             | engineers' belts
             | 
             | then the original FPers leave and now there's systems in
             | prod with little to no people who can work on it. that
             | rewrite suddenly got a lot more business-critical!
             | 
             | the original FPers weren't as PM-savvy, so the rewrite is
             | successful despite having less functionality and still
             | taking a year or more. doesn't matter - the savvier
             | managers and engineers know how to set goals & milestones
             | that they know they'll hit and can say that they hit when
             | evaluating the project's success
             | 
             | This is just a summary of my years of experience as an FP
             | professional. I've seen this happen 3+ times across 3+
             | companies.
             | 
             | ---
             | 
             | Haskell is by far the most worth-it skill I've cultivated.
             | It wasn't easy but I really do do a 10x job on my personal
             | projects in large part due to it. It's just not a good
             | language to use in a corporate setting. It's better to get
             | paid big bucks to be less productive. Save the technical
             | brainpower for things you yourself find valuable :)
             | 
             | (and I sneak Haskell in all my jobs anyways - scripting,
             | for instance - so I still develop my Haskell knowledge on
             | company time & dime, despite the language being all-but-
             | banned by the higher-ups)
        
             | wyager wrote:
             | My previous employer would teach new employees to use a
             | functional language from scratch and people would be
             | productive in 2-3 weeks. I don't think it's actually that
             | difficult in reality.
        
         | guerrilla wrote:
         | I think it's more that you shouldn't use a tool that you're
         | incompetent at. It has nothing to do with how common or not it
         | is. Just know what you're doing or don't do it.
        
           | PragmaticPulp wrote:
           | > I think it's more that you shouldn't use a tool that you're
           | incompetent at. It has nothing to do with how common or not
           | it is.
           | 
           | These two points are closely related, though.
           | 
           | Common tools will always have more available programmers,
           | more documentation, more tutorials, more help, more
           | libraries, more maturity.
           | 
           | We had a server written in a functional language at a company
           | I worked at. It was fine, but when the two people who wrote
           | it left the company it became a huge pain point to even hire
           | someone to work on it. Consultants knew this and demanded
           | exorbitant fees for basic work on the project.
           | 
           | Eventually we just rewrote it from scratch in a common
           | language and saved a huge amount of time and money compared
           | to trying to build teams and schedules around this obscure
           | language.
        
             | guerrilla wrote:
             | > more documentation, more tutorials, more help, more
             | libraries, more maturity.
             | 
             | Haskell's got all that but I can't argue with it needing
             | more programmers.
        
             | [deleted]
        
             | cerved wrote:
             | which language?
        
             | AzzieElbab wrote:
             | What if I told you that common languages are rapidly
             | adopting futures from functional languages? Go being a
             | notable exception.
        
               | PragmaticPulp wrote:
               | > What if I told you that common languages are rapidly
               | adopting futures from functional languages?
               | 
               | I use functional paradigms in mainstream languages. No
               | need to be snarky or sarcastic.
               | 
               | That's not what this article is about, though. Using Elm
               | and Haskell for projects is not mainstream.
        
               | Jasper_ wrote:
               | As far as I know, the Future concept for async/await
               | started with Twisted's Deferred, which is a framework for
               | Python. It's not really from functional land.
        
               | cerved wrote:
               | futures have been around since the 80s afaik
        
               | nextaccountic wrote:
               | Futures were first proposed in 1976, in a book called
               | "The Impact of Applicative Programming on
               | Multiprocessing". [0]
               | 
               | Applicative programming is an older term for functional
               | programming[1], but note this isn't pure functional
               | programming like in Haskell; it's functional programming
               | like in Scheme and Javascript.
               | 
               | [0] I can't find a pdf of the book, but it was mentioned
               | here https://en.wikipedia.org/wiki/Futures_and_promises -
               | the book calls it promises
               | 
               | [1] https://en.wikipedia.org/wiki/Applicative_programming
               | _langua...
        
               | rowanG077 wrote:
               | I don't think python invited a single thing tbh.
        
         | Igelau wrote:
         | Really I think the mistake there was not forking Elm. Maybe the
         | fork wouldn't have been popular long term, but at least they'd
         | ship.
        
           | PragmaticPulp wrote:
           | > Really I think the mistake there was not forking Elm.
           | 
           | Forking a framework and trying to maintain a new, separate
           | open source project is a huge burden. There is no way that
           | would have fixed their problems of being behind schedule, but
           | it definitely would have permanently worsened their
           | maintenance overhead.
           | 
           | They needed to scrap the alternate language/framework plans
           | and return to something safe and proven as soon as it became
           | obvious that they were too far off track. Continuing to
           | double down on commitments to unpopular frameworks (or worse,
           | creating your own niche fork to maintain) would only worsen
           | the problem.
        
           | adregan wrote:
           | I agree. Assuming this article is about the author's
           | experiences in early 2019, Elm has only had one release since
           | then. They wouldn't have missed out on much at all by
           | shipping with a forked compiler but would have gained a lot
           | of time to migrate.
           | 
           | The fork wouldn't necessarily need to be public either.
        
           | dimator wrote:
           | Rather than forking elm, there's purescript, which is unlike
           | elm in all the restrictive ways. It seems to have regular
           | releases and plenty of packages as well.
           | 
           | https://www.purescript.org/
           | 
           | https://pursuit.purescript.org/
        
           | sam0x17 wrote:
           | Yeah I was literally expecting the next paragraph to be "and
           | that's how elixir was born!"
        
       | exdsq wrote:
       | Mandatory Hitler reacts to Functional Programming comment
       | 
       | https://youtu.be/ADqLBc1vFwI
        
       | pjc50 wrote:
       | It's "monad is just a monoid in the category of endofunctors": if
       | you don't understand something, here is an explanation in terms
       | of other things you understand even less.
        
         | AzzieElbab wrote:
         | Monad is a thingie that lets you sequence computations in the
         | same context. Context being something like Future or Stream or
         | List
        
           | kayodelycaon wrote:
           | I'm not sure if this is supposed to be sarcastic or not but
           | it doesn't make any more sense to me.
        
             | yudlejoza wrote:
             | One way to think of a monad is through the example of a
             | shell (e.g., bash) pipeline:
             | 
             | # cat data.csv | process-1 | process-2 | ... | process-n >
             | final-output
             | 
             | Imagine you have this pipeline that already works for
             | data.csv. But now you have data2.csv which has some
             | difference (e.g., some values are null, while the original
             | data.csv had no null values).
             | 
             | Monads are an approach to making the existing pipeline work
             | (with minimal changes) while still being able to handle
             | both data.csv and data2.csv. The minimal changes follow a
             | strict rule as follows (this is not a valid shell command
             | anymore):
             | 
             | # wrap(cat data.csv) ] process-1 ] process-2 ] ... ]
             | process-n > final-output
             | 
             | In other words, only two kinds of changes are allowed:
             | 
             | - You can bring in a wrap function, that modifies the
             | entries of the given csv data.
             | 
             | - You can bring in a new kind of pipe ']' instead of '|'
             | 
             | The idea being, the wrap function takes in original data
             | stream, and for each "unit" (a line in the csv file, called
             | a value) produces a new kind of data-unit (called monadic-
             | value). Then your new pipe ']' has some additional
             | functionality that is aware of the new kind of data-unit
             | and is able to, e.g., process the null values, while
             | leaving the non-null values unchanged.
             | 
             | Note, you didn't have to modify any of the process-1
             | through process-n commands.
             | 
             | BTW, the null value handling monad is called the 'maybe
             | monad' (and of course there are other kinds of monads).
             | 
             | If you make the existing pipeline work in this way, you
             | essentially created a monad to solve your problem (monad
             | here is the new mechanism consisting of the new value, and
             | the two new changes, the wrap function, and the new pipe).
             | 
             | edit: There may be a need to also modify the '>' mechanism.
             | But I think that is not essential to the idea of a monad,
             | since you could replace ">" with "] process-n+1 >" (i.e.,
             | you created a new outermost function 'process-n+1' that
             | simply converts the monadic-values back to regular values).
             | 
             | edit 2: If instead of handling null-values, the purpose is
             | to "create side-effects" e.g., at every pipe invocation,
             | dump all/some contents of the data into a log file, then
             | the kind of monad you end up creating would be something
             | like an "I/O monad".
        
             | chii wrote:
             | it doesn't make sense to an imperative programmer because
             | "sequence computations" is like water to a fish. the idea
             | that computation isn't always sequenced doesn't occur to
             | someone who hasn't encountered functional programming.
        
               | kayodelycaon wrote:
               | Not sure what you mean by that. Threaded and event-driven
               | systems don't necessarily have a predictable sequence.
               | Same with data flow through any non-trivial web
               | application using background processing.
               | 
               | I've worked on systems that run through a chain of
               | background workers. Each job had a complete list of
               | operations (one per worker) to preform. When each worker
               | finished, it posted the job back to the general queue
               | with the new state and one less operation to preform.
               | 
               | All programs are eventually sequenced. You can't work on
               | data that doesn't exist yet.
               | 
               | I'm pretty sure I don't lack the ability to understand
               | what your talking about. I am sure I don't know what the
               | words you are using mean.
        
               | ModernMech wrote:
               | As an educator, I get to see many young programmers learn
               | about functional programming usually around their
               | sophomore year of college. They've never used threaded,
               | event-driven, dataflow, or similar systems. All they know
               | how to write are single-threaded Java programs, and their
               | perception is that programs are "a list of statements
               | that tell a computer what to do, in order".
               | 
               | They are especially uneasy about the concept of lazy
               | evaluation. It goes against everything they know about
               | programming - that you write a line of code, it's
               | executed, and you move on to the next line of code. With
               | lazy evaluation (as in Haskell) it's an uphill battle
               | getting them comfortable with the idea of writing a line
               | of code that will be executed at some unspecified point
               | in the future. For many students, this can be a mind-
               | bending realization.
        
           | mdoms wrote:
           | Do you guys really look at a sentence like this and think,
           | "yup, that clears it up"?
        
           | nowherebeen wrote:
           | These context you list are higher order kinds.
        
           | wsc981 wrote:
           | This is actually a very understandable explanation, though
           | maybe 'thingy' should be replaced with 'mechanism'.
        
       | dustinmoris wrote:
       | Observation from the real world:
       | 
       | Functional programming seems to be extremely easy if you have
       | never learned imperative programming first. I have seen beginners
       | grasp FP much faster than OOP and write production ready code
       | only after a few weeks/months of learning whereas beginners need
       | on average multiple years to learn "production ready" design
       | pattern style OOP.
       | 
       | On the other hand I have observed some of the best OOP developers
       | really struggle with FP. It's not that they find FP hard to
       | learn, they find it _really hard_ to unlearn OOP and the thinking
       | that the way things are done in OOP is the holy grail of good
       | software design.
       | 
       | For example, only recently there was this blog post trending on
       | HN (Am I stuck in a local maximum -
       | https://blog.ploeh.dk/2021/08/09/am-i-stuck-in-a-local-maxim...),
       | which was triggered by a "blue tick" OOP programmer (tastapod on
       | Twitter - inventor of BDD) making false statements about FP
       | because he seemingly struggled learning it and wasn't able to
       | work out how to program without mutations. He came to the
       | conclusion that all functional programmers actually use mutations
       | by default and immutable data structures are not common in FP at
       | all. It was a completely unfounded assertion and clearly one made
       | from frustration by someone who was so hard wired into OOP
       | programming that they couldn't adapt to the FP way of thinking.
       | It was a prime example of an "old dog" (citing the original
       | article) finding FP harder than the new guys.
        
         | jacquesm wrote:
         | Yes, this is very true. It took me a lot of time 'unlearn' bad
         | habits about state and side effects before functional
         | programming really clicked. The interesting bit is that it made
         | my other programs better as well, because I still find myself
         | avoiding mutable state and impure functions.
        
           | dnautics wrote:
           | I'd personally say it's less about unlearning statefulness
           | and learning what the alternative tools are and not be
           | bullheaded and kick and scream about not having the tools one
           | is used to, e.g. map and reduce vs for and while.
           | 
           | Once you learn how to use them, their utility and benefit
           | (they explicitly limit the scope of the changes in the loop
           | and reduce mental overhead) become clear. But a lot of people
           | never get past "why can't I have a for loop" and don't get
           | there.
        
             | jacquesm wrote:
             | Map and reduce immediately clicked, the state thing had me
             | for the longest time ('how do you generate output, how do
             | you get a real world effect from a function'), those seemed
             | to me to be far more magical in the FP world than in the
             | step-by-step alteration of the environment that I was used
             | to from imperative programming.
             | 
             | It also seemed to map harder onto the real world than IP,
             | where instructions about piecemeal alterations seem to be
             | the way of the world.
             | 
             | It really clicked for me when I started to think in terms
             | of transformations, where each function performs a
             | transformation of the input on the way to some output. This
             | allows you to be 'pure' most of the way and to limit input
             | and output to the top layers of the program, where they
             | should be (should in my opinion).
        
         | agumonkey wrote:
         | Thre's a little bit of psychological esoterism too, fp is very
         | minimal, OOP gives people some new mystery rope to hang
         | themselves with. verbose syntax, procedures to follow, it's
         | probably psychologically a better impedance matching than 'a ->
         | 'a -> b -> ('a -> 'b) where people have to hold very very
         | evanescent ideas floating in the air without as much ways to
         | play with them.
        
       | motohagiography wrote:
       | I fail to learn Haskell about once every 5 years and sometimes I
       | think of functional languages as not languages for expressing
       | concepts, but more like a musical notation that denotes a set of
       | abstractions mapped to an underlying ontology made from things
       | you just train yourself on with practice - and then use the
       | functional language as a lookup reference to until you can in
       | effect "sight read," or compose those underlying elements to the
       | page. The algebra and category theory are the true instrument,
       | and the language is the composition notation tool. Whereas with
       | OO and imperative programming, the imperative or OO language
       | itself is the instrument or tool that you can just pick up and
       | bang away on and music will come out. To extend the metaphor, OO
       | is an instrument on which you can play a canon like "row your
       | boat" without knowing how to write one, some, or all of them.
       | It's lovely that we have these tools for specifying and composing
       | functions, but perhaps the gap is in effectively expressing and
       | teaching the underlying ontology. Maybe as a writer, my next
       | attempt should be to write that explanation of it as I go.
       | 
       | The most trouble I had with Haskell was pronouncing statements
       | after reading them, which prevented me from composing the ideas
       | in my head because the syntax doesn't give you a lot of hints.
       | It's like trying to parse calculus without names for the letters
       | in the greek alphabet. Most people are proficient in their own
       | written languages, and they are capable of mapping ideas to
       | abstractions, but if there is not a way to express those ideas
       | lexically in their language, most are going to stumble.
       | 
       | The incomplete and error prone explanations by novices that the
       | author refers to also create an artificial conceptual barrier,
       | but mostly because there is always the hint and implication (or
       | perhaps just personal anxiety) that you are not writing _real_
       | functional programs and that your naivety is accumulating a
       | hidden sunk cost that you will eventually be exposed for and made
       | ashamed of because you aren 't a category theorist, which is a
       | consequence of this mostly aesthetic idea that functional code is
       | about competing to advance knowledge in a science and not just
       | making stuff you enjoy or people like. The clostest thing I found
       | to a kind of _function-punk_ where you could just bang away on it
       | because it was fun was the excellent
       | Learnyouahaskellforgreatgood, but it focused on the notation less
       | than the underlying ontology - e.g. the instrument - and what I
       | think I might need is more of a _category-punk_ that provides the
       | equivalent to composition with a few concepts, and then add the
       | notation to those.
       | 
       | Not sure there's another attempt in me, but anyway, provocative
       | article about something so important, and that I think ultimately
       | FP will really advance the way people think about the world, if
       | only in another generation or two.
        
       | del_operator wrote:
       | Teaching someone to abstract out a name for something they want
       | to do takes lots of practice, but then when they are pushed to
       | have to abstract can lead to decision paralysis around when to do
       | it. Having folks practice this together and feel out the nuances
       | helps a lot. Control flow is also a tricky early concept for any
       | new programming setting, but also, learning to compose is too.
       | For some students tackling control flow and composition early by
       | explicitly composing abstracted funcs feels great. However, I've
       | oft seen many of my students want to get granular with control
       | flow for a long while before they abstract or utilize many
       | abstractions, probably because their mental model of what they
       | want to do is stepping through each detail of an example they
       | have in mind. Another component for andragogical learning is to
       | just sell the WHYs of functional patterns: why care, why
       | remember, why it's helping, why they should just give it 5, why
       | it's ok to forget, et cetera. Learning and jumping straight into
       | synthesizing, evaluating and analyzing code for a potential
       | production setting has been difficult with a loose understanding.
       | You need good scaffolding in your backlog, lots of time,
       | patience, context sharing, and resourceful experts to turn to
       | check your understanding and promote good tooling/solutions in
       | the ecosystem. I saw this when my team switched to elixir. I saw
       | this when my team stitched to K8s. Lots of delays I'm happy we
       | worked through. Pairing a lot helped through it
        
       | Igelau wrote:
       | Lisp has always seemed like the most teachable FP language to me.
       | I imagine it would be hard to start elsewhere.
        
         | cerved wrote:
         | Haskell seems like a terrible language to start with
        
           | wyager wrote:
           | Disagree. I think it's a lot easier to learn than something
           | like C++ or Java, which a lot of people start with. People
           | just tend to forget how much they struggled with these very
           | complicated languages when they were getting started.
        
             | cerved wrote:
             | I meant of the functional languages
        
             | Igelau wrote:
             | You make a good point. It's been a long time since "do a
             | cout" seemed like a reasonable way to think about output in
             | C++.
        
         | abeppu wrote:
         | Yeah, it seems weird that the author latched onto some things
         | as part of their definition of "functional programming" which
         | aren't really required. I still find SICP to be an impressive
         | self-contained foundation for functional programming, and
         | "Functor" and "Monad" aren't mentioned as named concepts.
         | 
         | Is there a better name for the domain the author is talking
         | about? "Type-driven functional programming"?
        
         | rightbyte wrote:
         | FP with dynamic scoping?
         | 
         | Lisp is not a FP language anymore than C.
        
           | Jtsummers wrote:
           | Sure it is. Using the "Appeal to Wikipedia Fallacy":
           | https://en.wikipedia.org/wiki/Lisp_(programming_language)
           | 
           | Most Lisps are multiparadigm, covering at least the
           | functional and procedural paradigms. Going to Common Lisp you
           | can add OO to the mix. It is a severely constrained notion of
           | FP that manages to exclude the first functional programming
           | language from its definition.
        
           | lispm wrote:
           | Lisp only has dynamic scoping? C comes with first class
           | function objects, closures, ... ?
        
       | legobmw99 wrote:
       | My two cents is that anything is hard to learn without an
       | application you can test your knowledge against. It's always hard
       | to learn language X until you go ahead and build something in it.
       | 
       | Functional programming is hard because in a lot of cases,
       | especially ones beginners encounter, the imperative solution is
       | simpler. Purity and types are things I think you only truly
       | appreciate when you're writing large or complicated programs. I
       | wasn't able to really grasp FP (beyond using things like map() in
       | Python) until I took a compilers course which used OCaml, and the
       | ability to pass around and destruct these very complicated
       | immutable trees was a very natural problem to tackle in the
       | domain
        
         | throwaway81523 wrote:
         | > My two cents is that anything is hard to learn without an
         | application you can test your knowledge against. It's always
         | hard to learn language X until you go ahead and build something
         | in it.
         | 
         | If it's something really new and different, like Haskell is to
         | an old school imperative programmer, I think the opposite
         | approach is best. Treat it like a topic in math, start from
         | zero, work out small problems to exercise the basic concepts,
         | then start putting them together.
         | 
         | Immutable data structures are another new and shocking thing,
         | but less complicated than fancy typed FP is. Start with seeing
         | how you can "update" the first element of a linked list by
         | making a new first element and linking it to the existing tail.
         | Then see how AVL or red-black trees let you do something
         | similar with tree nodes in log(N) time, so you can use those
         | instead of hash tables without a monstrous slowdown. That's
         | probably all you need, but the next thing after is probably
         | Chris Okasaki's book Purely Functional Data Structures. It is
         | pretty readable once you've seen some basics.
        
       | chadcmulligan wrote:
       | Maybe one of you functional gurus can answer this - One of the
       | problems I have with functional programming is how do you handle
       | multiple data structures on a single thing. For example - say you
       | have a drawing program, with say just one shape - a square. Now
       | to make it fast when the user clicks somewhere you'd have a data
       | structure like a k-d tree that can find your shape quickly. Now
       | you also have another structure a list of the shapes, because you
       | don't want to put them in the k-d tree, you update both
       | structures when shapes change. You'd also want other structures
       | for say undo/redo. I can't see anyway to do this in functional
       | programming. Same applies to database style programming.
        
         | hvocode wrote:
         | That's not that hard in an FP language. I routinely write code
         | with multiple structures referring to the same thing. My usual
         | solution is to have an identifier for the thing that indexes
         | into an array or map, and then the other structures contain
         | that ID instead of the object itself. It's basically a pointer
         | like I'd use in any other language. The details and choices for
         | how to represent the IDs and structures is usually application
         | specific, but that's true in any language: how you do something
         | should be the choice that best fits your problem. There isn't
         | anything about functional programming that makes it impossible
         | or particularly difficult.
        
           | chadcmulligan wrote:
           | ok, cool, would you know some sample code somewhere you could
           | point me to? Just to see an example, always thought you
           | couldn't do this.
        
       | Mikeb85 wrote:
       | Functional programming is hard because some proponents of it
       | spend more time on theory and proving why you should use FP than
       | simply doing things with it. That's why most things shipped with
       | FP is created with languages like Ocaml, Scala, JavaScript,
       | Clojure, etc... You know, functional but more pragmatic and
       | multi-paradigm.
        
       | yodsanklai wrote:
       | It's not hard at all. It's routinely taught to beginners.
       | 
       | However, it's not a silver bullet. I found that basic software
       | engineering principles are way more important than the language.
       | I've seen extremely messy OCaml code and super clean C code. What
       | is important is how the code is organized at high level. Whether
       | you use a for loop or a fold, an error monad or an exception
       | mechanism matters less.
       | 
       | I'm also wary of functional programming gurus that tend to over-
       | abstract things and use all the language latest features, making
       | code very hard to read.
       | 
       | Also, when developing in a niche language, you tend to miss
       | important tools and need to rely on unstable third-party
       | libraries.
       | 
       | I used to be quite enthusiastic about FP, but I think I'd stick
       | with more mainstream languages unless there's a good reason not
       | to.
        
         | swiley wrote:
         | Programming is about clearly communicating theory.
         | 
         | Mariners use "port" and "starboard" for vehicle relative
         | directions not because it's "cool" but because it's clear and
         | unambiguous. Problem decomposition works the same way: some
         | problems decompose better with FP (I would argue databases do)
         | some with OOP, some with EF etc. The more you know the clearer
         | code you can write and the faster you can extract the theory
         | from other people's code.
        
           | IIAOPSW wrote:
           | What makes you say "port" and "starboard" are more clear than
           | "front" and "back"?
        
             | swiley wrote:
             | The alternatives are left and right respectively. They're
             | more clear because left and right are usually relative to
             | the speaker or listener who may be facing each other and
             | are often moving around.
        
             | byroot wrote:
             | It's not "front" and "back" it's "left side of the boat"
             | and "right side of the boat".
        
               | IIAOPSW wrote:
               | Oops.
        
               | WalterBright wrote:
               | More correctly, the "left side of the boat" and the
               | "other left side of the boat."
        
             | caconym_ wrote:
             | a) They refer to left and right, not front and back (which
             | I believe would be "forward" and "aft").
             | 
             | b) With the possible exception of "forward", if you hear
             | one of these words you always know it's specifying a
             | direction relative to the direction the boat is pointing,
             | which is not true for "left" and "right".
        
       | reverseblade2 wrote:
       | this 3d bin packer is fully coded in F# and I wouldn't be able to
       | do so without it.
       | 
       | https://bindrake.com/
        
       | [deleted]
        
       | bobcostas55 wrote:
       | One aspect I don't see mentioned very often is that the FP model
       | of computation is completely different from the model of the
       | underlying hardware, which makes it very difficult to reason
       | about things (and often involves putting blind hope in the
       | compiler).
        
       | macintux wrote:
       | I would dip my toes into FP occasionally (but very, very briefly)
       | for years. I bought a book on Scheme in 1995, to give you a sense
       | of how long I wandered in the wilderness.
       | 
       | It wasn't until I discovered Erlang in 2012 (thanks, _Seven
       | Languages in Seven Weeks_ ) that I finally found the motivation,
       | aided in no small part by the fact that it's a very simple
       | language and it's designed for server programming, where I've
       | always been happiest.
       | 
       | I still haven't graduated into category theory or type theory. I
       | still don't know the difference between a monad and a monoid. But
       | functional programming really speaks to me, because I have an
       | old, tired brain and I need pure functions wherever I can employ
       | them to keep things straight.
        
         | stadium wrote:
         | Pure functions concept was a breakthrough for me too. As a
         | design pattern they are wonderful, there is so much less mental
         | context to keep track of.
         | 
         | Now whenever I see mutated variables and class attributes, or
         | random side effects besides reading/writing to a database, it
         | kinda makes me cringe and think it's a "oh here we go" into a
         | rabbit hole just to understand what the code is doing. 9/10 the
         | code does what it's supposed to, but the mutations and side
         | effects makes understanding and extending it so much harder.
        
         | exdsq wrote:
         | A monad is just a monoid in the category of endofunctors
        
       | stackedinserter wrote:
       | Probably because every single FP tutorial is very far away from
       | real tasks that average software developer deals on everyday
       | basis.
       | 
       | They describe pure functions and categories of endofunctors,
       | while I have tasks like "invoke this stateful external API if
       | that stateful external API returns specific values".
        
       | jqgatsby wrote:
       | His daughter's question "Why do we use functions?" is something I
       | found myself asking during my math undergrad, and no one could
       | give me a straight answer.
       | 
       | To answer it to my own satisfaction, I eventually arrived at a
       | form of predicate logic so I could directly experience how
       | cumbersome it was to try to express everything that way. I liken
       | it to trying to speak in a language that lacks a definite
       | article: doable, but way more verbose.
        
         | polishdude20 wrote:
         | I always thought of functions as just boxes. We like to put
         | similar things in boxes because that lets us remove the
         | complexity of having to manage many similar things at once.
         | When you can just say "this group of balls here needs to be put
         | in the closet" you don't need to think or know that one is a
         | tennis ball, one is a basketball and one is a softball. A
         | function to me is just a way to wrap up a complicated idea or
         | task into a box. It's what we already naturally do with
         | everything in our lives.
        
           | dtagames wrote:
           | Indeed, but _functions_ are not the same thing as
           | _functional_ programming. (We reuse so many words in this
           | field!)
           | 
           | What you're describing are regular functions. If those
           | functions hold a _state_ , they're not functional; they're
           | procedural. For example, a function that holds onto a counter
           | and increments it by some value that is passed in _cannot_ be
           | functional because the counter exists in a hidden state,
           | unknown to anyone else and unpredictable until runtime. This
           | is what Backus was trying to fix.
           | 
           | A _functional_ version of that same function would need two
           | parameters, one for the amount to increment by and a second
           | one for the counter 's current value. Often, a function can
           | be rewritten in the functional style and thereby eliminate
           | state (at least from that function).
           | 
           | Whew!
        
             | polishdude20 wrote:
             | So at some point up in the heirarchy, you're keeping track
             | of that counter. So there will be a parent of the
             | incrementing function which is itself not a function
             | because it keeps state. You could say your top level
             | program is not a function because it keeps state.
        
               | Thiez wrote:
               | Not neccessarily, when your program is (tail-)recursive
               | you can carry the "current" value along without ever
               | really mutating it. Haskell has the State monad which
               | doesn't require any impurity.
        
             | scns wrote:
             | In Nim you declare func and proc IIRC.
        
         | Igelau wrote:
         | This is how I answer my kids' questions. "Why? Why? Why?"
         | Buckle up, kid, we're going down the rabbit hole. They usually
         | get bored before I do and have learned to back off when I slip
         | into presentation tone.
        
           | scns wrote:
           | Feynman gets asked how magnets work:
           | https://www.youtube.com/watch?v=MO0r930Sn_8
        
         | asimpletune wrote:
         | A function is just the concept of a thing that maps from a
         | domain to a range.
        
         | chimen wrote:
         | A function is a verb to me. It explains an action, just one.
        
         | emodendroket wrote:
         | Lots of languages lack definite articles without being notably
         | more verbose.
        
         | Zababa wrote:
         | I really think we should go back to calling things that are not
         | pure functions "procedures" or maybe "subroutine".
        
       | darksaints wrote:
       | It's just the Haskell family of functional programming languages
       | that is hard to pick up. There are plenty of functional language
       | families that are quite easy to understand and much more
       | pragmatic:
       | 
       | * ML - includes SML, OCaml, F#, Scala, and Rust
       | 
       | * Lisp - includes Common Lisp, Racket, Scheme, Clojure
       | 
       | * Actor Model - includes Erlang, Elixir, and Pony, as well as
       | other languages that have actor model systems at the library
       | level
       | 
       | You'll find endless sources of opinions on why the Haskell family
       | is so hard to use well. My personal opinion is that most
       | languages create abstractions with concrete types of problems in
       | mind. Haskell created abstractions with other types of
       | abstractions in mind. If you ask the question "what is a monad
       | used for?", the average Haskell user isn't going to respond in
       | any form about making side effects safer, because that's just one
       | thing that they do...they're going to respond with other
       | abstractions. And after 45 minutes of explanations of what they
       | are, they still haven't yet gotten to the explanation of what you
       | can do with it. And then when you finally understand what you can
       | actually do with it, you have to confront the fact that they made
       | an incredibly easy thing hard, just in case you might want to use
       | it a different way.
       | 
       | I cant recommend this rant enough -
       | https://existentialtype.wordpress.com/2011/05/01/of-course-m....
        
         | pyrale wrote:
         | > * ML - includes SML, OCaml, F#, Scala, and Rust
         | 
         | Scala and ocaml suffer from the same reputation. SML didn't
         | really make it out of the academia. F# is easier, but still has
         | a bad rap from C#ers. Rust is making incredible efforts to be
         | accessible, but the learning curve is still steep.
         | 
         | One could say haskell itself is also an offspring of the ML
         | family.
         | 
         | In that family, the article author correctly identified that
         | Elm is probably among the most accessible. Choosing a specific
         | application domain enabled the language creators to cut a lot
         | of complexity, and to use a simple state machine as a runtime.
         | 
         | > If you ask the question "what is a monad used for?"
         | 
         | You'll get the same kind of answers as you'd get you'd get when
         | asking Java programers what this "class" concept is about. The
         | functor-applicative-monad stack is at the heart of Haskell's
         | flavor of functional programming. You can write small programs
         | without it, of course, but it's going to be the same experience
         | as writing Java with a single "main" class.
        
         | mrdoops wrote:
         | Agreed. I would bet on a language like Elixir or F# being
         | simpler to learn and grow for a complex system than a class-
         | oriented-imperative-oop (Java, Ruby, Python, etc) language any
         | day.
        
         | JaggerJo wrote:
         | +1
         | 
         | We've been using F# with great success for a few projects now.
         | Our stack is super simple.
         | 
         | On the backend we use F# (on .NET with ASP.NET Core) +
         | Postgres.
         | 
         | On the frontend we use F# (via Fable with React and the Feliz
         | Bindings).
         | 
         | https://zaid-ajaj.github.io/Feliz/
         | 
         | And we have a huge shared library. Works like a charm.
        
       | [deleted]
        
       | cutler wrote:
       | I think learning functional programming is harder with a
       | statically-typed language as there's so much more to learn which
       | revolves solely around the type system. I would recommend anyone
       | new to FP to try Clojure first. No mon[a|oi]ds necessary. I also
       | think the transition from procedural languages is easier than
       | from OO languages. I was lucky not to be exposed to Java or C++
       | in the early days of my programming career, opting for Perl
       | instead. When I transitioned to Ruby I also encountered Clojure
       | at the same time and could appreciate the functional/lisp
       | elements in the design of Ruby.
        
         | stadium wrote:
         | I had only one FP experience with scala. I actually liked that
         | it was statically typed. I have nothing to compare it to
         | though.
         | 
         | But, higher order functions and type parameters are still a bit
         | mind bending for me. I didn't have to write much code for
         | those, but when I did it was really hard. I'm sure I'd need at
         | least couple days of reading and playing around to somewhat
         | grasp how to implement them again.
        
       ___________________________________________________________________
       (page generated 2021-08-15 23:01 UTC)