Why is Haskell (sometimes) referred to as “Best Imperative Language”?

后端 未结 3 681
小蘑菇
小蘑菇 2020-11-30 18:28

(I hope this question is on-topic -- I tried searching for an answer but didn\'t find a definitive answer. If this happens to be off-topic or already answered, please mo

3条回答
  •  猫巷女王i
    2020-11-30 19:17

    It's not a joke, and I believe it. I'll try to keep this accessible for those who don't know any Haskell. Haskell uses do-notation (among other things) to allow you to write imperative code (yes, it uses monads, but don't worry about that). Here's some of the advantages that Haskell gives you:

    • Easy creation of subroutines. Let's say that I want a function to print a value to stdout and stderr. I can write the following, defining the subroutine with one short line:

      do let printBoth s = putStrLn s >> hPutStrLn stderr s
         printBoth "Hello"
         -- Some other code
         printBoth "Goodbye"
      
    • Easy to pass code around. Given that I've written the above, if I now want to use the printBoth function to print out all of a list of strings, that's easily done by passing my subroutine to the mapM_ function:

      mapM_ printBoth ["Hello", "World!"]
      

      Another example, although not imperative, is sorting. Let's say you want to sort strings solely by length. You can write:

      sortBy (\a b -> compare (length a) (length b)) ["aaaa", "b", "cc"]
      

      Which will give you ["b", "cc", "aaaa"]. (You can write it shorter than that, too, but never mind for now.)

    • Easy to re-use code. That mapM_ function is used a lot, and replaces for-each loops in other languages. There's also forever which acts like a while (true), and various other functions that can be passed code and execute it in different ways. So loops in other languages are replaced by these control functions in Haskell (which are not special -- you can define them yourself very easily). In general this makes it hard to get the loop condition wrong, just like for-each loops are harder to get wrong than the long-hand iterator equivalents (e.g. in Java), or array-indexing loops (e.g. in C).

    • Binding not assignment. Basically, you can only assign to a variable once (rather like single static assignment). This removes a lot of confusion about the possible values of a variable at any given point (its value is only set on one line).
    • Contained side effects. Let's say that I want to read a line from stdin, and write it on stdout after applying some function to it (we'll call it foo). You can write:

      do line <- getLine
         putStrLn (foo line)
      

      I know immediately that foo doesn't have any unexpected side effects (like updating a global variable, or deallocating memory, or whatever), because it's type must be String -> String, which means it is a pure function; whatever value I pass, it must return the same result every time, without side effects. Haskell nicely separates the side-effecting code from the pure code. In something like C, or even Java, this is not obvious (does that getFoo() method change state? You'd hope not, but it might do...).

    • Garbage collection. A lot of languages are garbage collected these days, but worth mentioning: no hassles of allocating and deallocating memory.

    There's probably a few more advantages besides, but those are the ones that come to mind.

提交回复
热议问题