14

I'm interested in functional programming and decided to get head to head with Haskell. My head hurts... but I'll eventually get it... I have one curiosity though, why is the syntax so cryptic (in lack of another word)?

Is there a reason why it isn't more expressive, more close to human language?

I understand that FP is good at modelling mathematical concepts and it borrowed some of it's concise means of expression, but still it's not math... it's a language.

16
  • 4
    @ratchet freak: :) so is there one designed by a guy who hates polish notation?
    – JohnDoDo
    Oct 5, 2012 at 9:59
  • 11
    @ratchetfreak In what way does Haskell syntax resemble polish notation? Haskell operators are infix, just like most other languages' operators (and function calls are prefix - also like most other languages' function calls).
    – sepp2k
    Oct 5, 2012 at 10:01
  • 10
    That's a pretty big assumption/leap you're making, that "closer to human language" equates to "more expressive."
    – Matt Ball
    Oct 5, 2012 at 15:06
  • 7
    Ever heard of Cobol and Fortran?
    – ott--
    Oct 5, 2012 at 15:24
  • 7
    For exactly the same reason that mathematicians replaced long latin phrases with algebraic expressions. With a little practice, a more compact notation is a lot more productive. Oct 5, 2012 at 20:23

8 Answers 8

14

Functional languages like Haskell and its antecedent Miranda grew out of the mathematical concept of lambda calculus. From the Wikipedia page:

Lambda calculus (also written as λ-calculus or called "the lambda calculus") is a formal system in mathematical logic for expressing computation by way of variable binding and substitution.

...

Lambda calculus has played an important role in the development of the theory of programming languages. The most prominent counterparts to lambda calculus in computer science are functional programming languages, which essentially implement the calculus (augmented with some constants and datatypes). Beyond programming languages, the lambda calculus also has many applications in proof theory. A major example of this is the Curry–Howard correspondence, which gives a correspondence between different systems of typed lambda calculus and systems of formal logic.

Because of this history, the syntaxes of these functional languages (and functional elements of more imperative languages) are strongly influenced by the mathematical notation used by lambda calculus.

The precision with which both mathematical notations and computer languages can describe requirements and the precision with which computers require their instructions to be written correlate well with each other. The imprecision of natural language however creates a huge barrier to it's use for programming computers. Even the (arguably) most successful Natural language programming environments such as Wolfram Alpha need significant domain experience to be used effectively.

31

Haskell syntax is close to human language. It is specifically designed to resemble mathematical notation, which is a language designed by humans (thus a human language) to express precisely those concepts that Haskell is built upon.

You can show a piece of Haskell code to any mathematician or logician, and he will be able to understand it, even if he has never ever heard of Haskell and knows absolutely nothing about programming, computer science or even computers.

On the other hand, you can show any mathematician or logician a piece of code like this:

x = x + 1

and he will be utterly confused, saying: "This doesn't make sense, there is no x such that x equals x plus 1."

Whether or not some specific notation is "cryptic" or not, is a matter of opinion and familiarity.

12
  • 8
    There is just one problem with this answer: I'm not a mathematician.
    – JohnDoDo
    Oct 5, 2012 at 10:15
  • 7
    @sepp2k: I'd disagree. For most people w/o prior exposure to programming languages and some basic mathematical background Haskell syntax will be much simpler to understand than typical procedual code with all its side effects and the complicated environments statements are execute in. Syntax like where allow to condense the gist of a function in one line. Oct 5, 2012 at 10:21
  • 17
    -1: this answer seems largely pedantic. I'm fairly certain the OP meant spoken language. Oct 5, 2012 at 16:25
  • 6
    Actually, I'm pretty sure that x = infinity does indeed solve the equation.
    – DeadMG
    Oct 5, 2012 at 19:08
  • 6
    Well, programming languages are also designed by humans.... Thus by your definition, they are human languages. Oct 5, 2012 at 20:07
13

I think one thing you're probably running into is something that I ran into too when learning functional programming, which is that with functional programming you can (and almost have to) think/work at a higher level than you do with imperative programming.

What you're finding as less expressive, I think is actually more expressive: you don't have to spell out every little detail and can do more with less code in functional programming -- there's more power to what you write.

For example, I could write imperatively:

for each (Person person in people)
    print(person.name)

which is totally legible as English.

A Haskell version might be (and this is not valid Haskell, but is just for syntactic comparison):

map (print . name) people

which requires less code and less detail wrangling -- I don't have to break things down into a loop and its variable(s) (for each (...)), the map function takes care of that for me.

Working at that level can take some getting used to. If it helps any, Haskell was probably the toughest time I've had learning a new language since I started programming, and I know >10 languages (including Lisp). It was totally worth learning though.

8

I'm currently getting to grips with Scala at the moment, so I can sympathise. At least with Scala I can fall back to an imperative style when the going gets too tough.

I think there are several forces at play here:

  • Designers of functional languages necessarily have a strong maths background, so they borrow mathematical notation which is natural to them.

  • Greater expressiveness (i.e. power of statements, rather than closeness to English) of any language has (IMO) a corresponding price in steepness of learning curve. Terseness is a highly prized quality in Scala, with many things being optional.

  • Functional languages just do things very differently, so the basic operations don't map onto imperative constructs.

2
  • 3
    I would also add that often functional languages can express higher order concepts, these being more abstract, are harder to meaningfully name
    – jk.
    Oct 5, 2012 at 10:33
  • 1
    @jk, yes, agreed! At the same time, it's why they have a steep learning curve for programmers with imperative background and little math (like me), and why they are worthwhile. Oct 5, 2012 at 10:37
3

If I understood your last comment correctly, your question is why Haskell often uses symbolic operators in places where it could as well use alphanumeric keywords (or function names)?

Regarding keywords one answer would be that keywords prevent you using certain words as variable names. For example I'm always annoyed when I want to call my variables from and to in a languages where one of those is a keywords - like in Python.

Another reason for symbolic operators in general is conciseness. That doesn't really apply in your specific examples of list comprehensions (<- isn't shorter than in), but in many cases it does.

Yet another reason is readability. That might seem counter-intuitive because symbolic operators are often harder to learn since their "names" don't really tell you anything about what they do (while a function's name usually will), but once you do know what a given operator does, expressions with infix symbolic operators are often easier to parse for a human than one with lots of alpha-numeric prefix function calls since the operators are more easily visually distinguished from the operands that way. For example most people would agree that 2 * 3 + 4 is more easily readable than add (mult 2 3) 4 or add(mult(2, 3), 4).

1
  • @PeterTaylor Nope, just me being stupid ;-) Fixed now.
    – sepp2k
    Oct 5, 2012 at 17:39
3

Imperative computer languages mostly aren't any closer to natural languages than, say, Haskell is.

However, some are designed to more closely resemble English: Cobol and Hypercard, for example. The lessons I would take from these examples are:

  • similarity to natural languages doesn't seem to yield direct improvements in usability
  • emulating natural languages directly can yield computer languages that are verbose and obscure

The Perl computer language was reportedly designed with some more subtle aspects of natural language in mind. I would judge that Perl does better than Cobol or Hypercard on general usability, but people have differing opinions about Perl.

3

I think Haskell gets as similar to human language as one can get without introducing a crazy syntax. It really goes great lengths towards this, for instance with the where clause to postpone a definition and with the list comprehension syntax which is exactly what I would write on a blackboard. It also avoid extraneous characters like braces and has a liberal use of indentation. The typical example is quicksort:

qsort [] = []
qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
               where lesser = [x | x <- xs, x <= p] 
                     greater = [x | x <- xs, x > p]

Admitted, it is a simple example, but I do not know any other language that gets it as readable as this is.

Doing more complicated stuff can become difficult to read in Haskell, but that has to do with the type system, the constrained IO and not with the syntax at all.

If anything, I would say that Haskell has sacrificed syntactic simplicity in order to accommodate a syntax which is more similar to human language. A language like scheme has a syntax that is very far from what a human would write, but it is really simple to explain its rules.

5
  • 3
    I'd hardly call that human-readable. I know quicksort. I'm familiar with how to set it up in multiple different languages, I know what it's supposed to do, and I still can't make heads or tails out of the bottom half of that code snippet. Oct 5, 2012 at 16:21
  • I guess it really depends on your background. This is as plain as it gets for me...
    – Andrea
    Oct 5, 2012 at 16:26
  • 2
    In any case, it is supposed to resemble this notation: purplemath.com/modules/setnotn.htm
    – Andrea
    Oct 5, 2012 at 16:49
  • 4
    Are you sure it shouldn't be ++ [p] ++? Oct 5, 2012 at 17:15
  • 1
    @Mason: It seems pretty clear to me, and I've never written a line of Haskell Oct 5, 2012 at 20:21
2

I think the difference has to do with the way functional/declarative programming makes statements about a problem as though it's a math problem, where as imperative programming describes a process. In the business world, computer programs wrap or replace physical processes, so you may find a language that reflects this to be more intuitive.

It turns out that the functional style lends itself to making safe use of multiple processors (because it minimizes mutability and side effects) - something we will see more of in the future. Also, most modern functional languages have collections with iterators you can pass functions to. These methods can split their workload over multiple processors very efficiently without you even knowing about it.

1
  • I think this is the best answer - the only one that makes the distinction clear between process and statements.
    – Milind R
    Nov 2, 2014 at 5:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.