Live data from Hacker News

Teenage Haskell

twdkz.wordpress.com

81–90 of 93 posts

Re: Teenage Haskell

#81
post #80

Earlier quoted context omitted.

We were lucky in that Opal wasn't ready yet. :-P But we were horrified by what we heard about it. So we were spared that particular disaster, which was and is sold using the same "unquestionable superiority" rhetoric. Instead we dealt with Hope. As in "I Hope it will finish in the next 15 minutes". "It" being a 10-30 line program. Usually it didn't, instead producing a largish coredump. Our Sun 3-50 diskless workstat…

Well you have to take into account the amount of effort, time and manpower spend on different languages and (in-)directly on different paradigms. FP hasn't been given as much attention as imperative programming languages, especially not when it comes to the important last step of language development, which turns ideas that are nice in theory into tools that are actually convenient to use. Java is a good example for…

Your make some good points, but I don't quite buy them.

Turbo Pascal for example was written by a single guy, Anders Hejlsberg, in about 2 years for several platforms in assembly language, and included an integrated (though primitive) text editor/IDE.

Smalltalk was taken from ST-72 to ST-80 in 8 years, with small teams that also had to invent/implement complete VMs, operating systems, bitmap graphics engines, GUI framework(s) and sophisticated IDEs. You write that it would be nice to have an FP IDE so it could give you better feedback (or were you talking about an existing FP IDE). These guys built the live IDE (even better than types for direct feedback) in a fraction of the time. Does OPAL still compile to C? Does it still use Tk?

Think about Ruby, Python, etc.

I could go on (the VPRI stuff is also amazing), but I think you get the idea: it seems that not only can you be a productive member of society without FP, it sure looks like people can be a lot more productive without FP than with it.

Java is not really a good example of anything. Certainly not of an OOPL: "Java is the most distressing thing to happen to computing since MS-DOS." "If the pros at Sun had had a chance to fix Java, the world would be a much more pleasant place. This is not secret knowledge. It’s just secret to this pop culture." — Alan Kay (who coined the term "object oriented")

I don't quite get why you see LISP as an example for the power of FP, it is a multi-paradigm language with some functional elements, and most of its power comes, AFAIK, from its meta-system.

And HOFs like map or fold have been in other languages since the dawn of time, they're certainly in Smalltalk.

In terms of rhetoric, Peter Pepper might seem like an outlier, but as far as I can tell he is not. You can see it in this very thread: if you don't buy the self-evident awesomeness, it must be because "you didn't understand" and "refuse to understand", it cannot possibly be because you legitimately have a different point of view.

Another example. I watched the following talk by Simon Peyton Jones on data parallel Haskell:

https://www.youtube.com/watch?v=NWSZ4c9yqW8

Interesting stuff. But he has to go and say it: "this is only possible in a pure FP language like Haskell". Hand raised in the auditorium. "Actually, this sort of thing is pretty common in the HPC community, in FORTRAN [under some specific name]". And of course he can't just shut up and read up on things he obviously doesn't know about, he has to retort: "well, that means that it is nothing but a variant of Haskell at this point". Ouch! And finally, at the end of the talk he gives some numbers. It turns out that this amazing thing that's only possible in Haskell needs 6 cores to match the performance of a single core C program. 6:1. That's absolutely pathetic, especially when compared to what the HPC FORTRAN guys are doing. So maybe he shouldn't be lecturing them, they know this stuff a lot better then he does.

Now don't get me wrong, the talk was interesting and thought provoking, but the mismatch between grandness of the rhetoric and the paucity of the results was its usual epically proportioned self.

Re: Teenage Haskell

#82
post #15
post #7

I never tried Haskell, or 'functional programming". To be honest, I don't even know what functional programming is. Can someone explain how is it different from Python or C (the only two languages I did little coding with)?

Basically, the difference is that in a functional programming language, words like "variable" and "function" have the same meaning they do in mathematics. In C or Python, a "variable" is a storage location in which you can place different values at different times. This is completely different from mathematics, where "x" doesn't equal something different just because you progress to the next step of computation. (But…

Thanks for your response. I've read it several times, but unfortunately it didn't click for me.

>>>Similarly, in mathematics, there's no such thing as a function that returns something different each time you evaluate it, or that gives one result on Wednesday but a different result on Friday

I don't get this example. If the function is f = t, where t is time, then f will give different results on Wed and Fri.

In both math and Python, a function such as Square = x*x will return exactly the same thing as long as x does not change.

>>>This is completely different from mathematics, where "x" doesn't equal something different just because you progress to the next step of computation

When I do math (such as algebra, or calculus), I think of a variable x as a container that can hold any value. This is exactly how I think of a variable in C or Python.

For example, I can build a graph of a parabola in Python. The way my code does it is pretty much the same as if I did it by hand with a pencil: I assign multiple values to x, and find corresponding values for y.

I can't quite pinpoint the source of my confusion...

Re: Teenage Haskell

#83
post #77
post #7

I never tried Haskell, or 'functional programming". To be honest, I don't even know what functional programming is. Can someone explain how is it different from Python or C (the only two languages I did little coding with)?

Some other descriptions here do a good job. It's worth being clear that "functional programming" is more of a set of similar but different programming cultures than a hard-and-fast language property. That said, one thing that's more common in FP than anywhere else is an adherence to the notion that a variable stands for an "unknown" and not a mutable slot. Thus, you cannot assign to a variable but instead can only de…

Thanks for you response.

>>>a variable stands for an "unknown" and not a mutable slot. Thus, you cannot assign to a variable but instead can only define it within a context.

I'm struggling to understand this. A variable in C is also 'unknown' until you assigned a value to it. Do you, or do you not, assign a value to a variable in FP? If not, then what do you mean when you write "x = 3"?

>>>variables which behave as unknowns instead of mutable slots are very easy to reason about and functions as first class values are very expressive.

Can you show me an example? A short FP code that illustrates your point when compared to an equivalent code in Python or C?

Re: Teenage Haskell

#84
post #83
post #77

Earlier quoted context omitted.

Some other descriptions here do a good job. It's worth being clear that "functional programming" is more of a set of similar but different programming cultures than a hard-and-fast language property. That said, one thing that's more common in FP than anywhere else is an adherence to the notion that a variable stands for an "unknown" and not a mutable slot. Thus, you cannot assign to a variable but instead can only de…

Thanks for you response. >>>a variable stands for an "unknown" and not a mutable slot. Thus, you cannot assign to a variable but instead can only define it within a context. I'm struggling to understand this. A variable in C is also 'unknown' until you assigned a value to it. Do you, or do you not, assign a value to a variable in FP? If not, then what do you mean when you write "x = 3"? >>>variables which behave as u…

An unassigned variable in C is not "an unknown", though it is (as an adjective) unknown. It's uninitialized and thus equal to some value though it must be initialized first in order to be useful since only then do we know how to predict its behavior.

To break down the difference, consider the idea of names versus the idea of "boxes" or "slots". In some languages those two concepts are undistinguishable because names always refer to locations in memory. In "functional"[1] languages they are separate.

As an example, consider a function in a hypothetical language

    def foo (y, x):
      let z = get(x)
      assign(x, y*y+z)
The (side) effect of this function is merely to update the value stored in the slot named `x` using a function of the value named `y`. To do so, we read from the slot `x`, bind a local name `z` with that value, and then assign back to the slot named `x`. We would call it in a block like this

    let box = newBox(1)
    let inp = 3
    foo(box, inp)
    let newVal = get(box)
    print(newVal)
and it would print `7` (3*3+1).

I'm being really explicit about the idea of things being "named" by variables instead of just "being" variables. I'm also being really explicit about the notion of how boxes undergo mutation. The reason I do this is to isolate this "naming" property and show how simple it is. Variables-as-unknowns are merely names of values given to them in some context. Usually this is either a function abstraction or a let

    let x = 3
    # now, here, the name `x` refers to a value `3`

    def foo(x):
      # now, here, the name `x` refers to some value that
      # will later be passed to `foo`
If we need mutation we have to introduce the box idea noted earlier. Boxes with names behave quite similarly to "memory address variables" like what you have in C.

[1] For this given definition of "functional"

Re: Teenage Haskell

#85
post #84
post #83

Earlier quoted context omitted.

Thanks for you response. >>>a variable stands for an "unknown" and not a mutable slot. Thus, you cannot assign to a variable but instead can only define it within a context. I'm struggling to understand this. A variable in C is also 'unknown' until you assigned a value to it. Do you, or do you not, assign a value to a variable in FP? If not, then what do you mean when you write "x = 3"? >>>variables which behave as u…

An unassigned variable in C is not "an unknown", though it is (as an adjective) unknown. It's uninitialized and thus equal to some value though it must be initialized first in order to be useful since only then do we know how to predict its behavior. To break down the difference, consider the idea of names versus the idea of "boxes" or "slots". In some languages those two concepts are undistinguishable because names…

I don't know, something must be wrong with my head, because I'm not any closer to understanding the point of FP. I really do want to understand it though.

Your hypothetical language - is it functional? Because if it is, I don't see how it's different from C. If it's not, can you show me the equivalent code in a functional language?

This is how I understand your code example:

def foo (y, x): let z = get(x) assign(x, y*y+z)

Jump to address 'foo', passing a value stored in register y, and an address stored in register x. Load value at address(x) to register z, then manipulate values of y and z, and store the result at address(x). So far so good.

let box = newBox(1) let inp = 3 foo(box, inp) let newVal = get(box) print(newVal)

Allocate memory for an int, put 1 in there, and store a pointer at register 'box'. Next, put 3 into register 'inp', and jump to 'foo', passing values at 'box' and 'inp' as x and y (registers don't change). 'Foo' updates the value at the address which we refer to as 'box' or 'x', and we load this value to register 'newVal', and print it.

The way I see it, if you are using a concept of a 'slot' or a 'box' in your code, you have to use some name (label) to refer to the address of this slot. This label would be the name of a pointer in C, or the name of a variable in Python. If you are using a variable which stores a value directly, the name of such variable points to a register.

How can you separate a name from what it points to? What would it mean, and most importantly, why would you want to do that?

Re: Teenage Haskell

#86
post #61
post #57

Earlier quoted context omitted.

> It's a matter of there actually being principles instead of the alternative; nothing. BS principles are not better than no principles. Or principles that tie your hand around your back for that matter. And functional principles do that for a lot of cases, with respect to performance, memory impact etc. Functional languages are not some kind of 2x or 10x multiplier of a programmers abilities. In fact most of the thi…

Python is an amazing language. I have been using it to do all my automation and scripting work for a long time. However, Python programs almost always feel like they were held together with string. I recently have been putting a lot of time into learning Haskell and it is amazing. The type system gives me so much confidence, and I have now reached a stage where writing Haskell programs is as concise and fast as writi…

The problem with the "canonical" Haskell Quicksort implementation is that it is utter tosh.

The whole point of Quicksort is being a fast and in-place sort. That's its entire reason for being (the name kinda gives it away). An algorithm that's slow and not in place is not Quicksort and not "the essence" of Quicksort either. It's some other sort ("Slowsort"?) loosely inspired by a cursory reading of Qicksort and not understanding what Quicksort is about and why it is "quick".

The whole thing is somewhat typical though: "We have discovered that the essence of is ". No, you have discovered a mapping function from to That's not the same as "the essence".

Re: Teenage Haskell

#87
post #85
post #84

Earlier quoted context omitted.

An unassigned variable in C is not "an unknown", though it is (as an adjective) unknown. It's uninitialized and thus equal to some value though it must be initialized first in order to be useful since only then do we know how to predict its behavior. To break down the difference, consider the idea of names versus the idea of "boxes" or "slots". In some languages those two concepts are undistinguishable because names…

I don't know, something must be wrong with my head, because I'm not any closer to understanding the point of FP. I really do want to understand it though. Your hypothetical language - is it functional? Because if it is, I don't see how it's different from C. If it's not, can you show me the equivalent code in a functional language? This is how I understand your code example: def foo (y, x): let z = get(x) assign(x, y…

Let me see if I can clarify.

Imagine a (rather useless) program that prints a number.

x = 5 x+=2 print x print x

this prints the number 7 2 times

in the 'context' definition of equality, which we'll denote using let * = ..., each of those assignments generates a context, which I'll show using indentation.

let x = 5 let x = x + 2 print x print x

These two programs do the same thing. However, using names as mathematical variables instead of 'boxes', there is another program we can create using the same 'sequence' of expression tokens (thus giving us greater expressive power).

let x = 5 let x = x + 2 print x print x

this program prints 7, and then it prints 5. In other words, we are able to access previous values of our 'variable' x if we want to, whereas this is not the default behavior of a system with mutable variables. This has an added benefit, not really shown in the previous example, of providing zones of protection from interference from the rest of the program. For example, I can always be assured that within the first context, x will always mean 5, and within the nested context, that x will always mean 7. No function or outside line of code can impact the value that x takes on. This really shines when programming in a team - this gives you assurance that to change the output of your section of the code, another teammate will have to directly alter your code. This localizes the source of future bugs in this code to always be in this section of the code, drastically simplifying the debugging process.

To make these contexts space efficient, modern functional programming compilers analyze when a program no longer needs access to previous value (because they will never again be used in the future), and marks it as 'garbage' to be collected later.

To try and rephrase it one more time - A mutable variable is an actual location in memory. Anyone sharing access to this location in memory in effect has a communication channel open to all of the other linking bits of code. This can be a powerfully simplifying abstraction, in some cases, which is why functional languages generally still provide it by many means, including (in Haskell) the State and IO monads. However, as a default model of resource usage, mutable variables are a poor choice. Generally speaking, you don't really want all parts of the code to be talking to one another. As programmers, whether using procedural, object-oriented, or functional programming, minimizing this kind of communication can help minimize the impacts of future changes. This is why object-oriented languages have private methods and variables, and why there is a trend towards object composition over object inheritance to define more complex behaviors, because both decouple the resulting subsets of code and make them more robust to external forces. Mathematical variables simplify our attempts to achieve this by cutting off the default route for breaking these hierarchical assumptions - shared communication.

Re: Teenage Haskell

#88
post #85
post #84

Earlier quoted context omitted.

An unassigned variable in C is not "an unknown", though it is (as an adjective) unknown. It's uninitialized and thus equal to some value though it must be initialized first in order to be useful since only then do we know how to predict its behavior. To break down the difference, consider the idea of names versus the idea of "boxes" or "slots". In some languages those two concepts are undistinguishable because names…

I don't know, something must be wrong with my head, because I'm not any closer to understanding the point of FP. I really do want to understand it though. Your hypothetical language - is it functional? Because if it is, I don't see how it's different from C. If it's not, can you show me the equivalent code in a functional language? This is how I understand your code example: def foo (y, x): let z = get(x) assign(x, y…

The language is sort-of functional. It's as unfunctional as possible while still highlighting immutability.

The key is to focus on what you can't do. Pointers in C do provide a similar UI to "boxes" that I was describing. But their plain values aren't the same. Consider

    int main() {
      int x;
      x = 3;
      x = 4;
      printf("x = %i\n", x);
    }

    $ gcc test.c -o test
    $ test
    x = 4
Here, I am still able to treat the value `x` as a "box" because `x` is not a name but instead an actual int-sized memory location on the stack. Here's a similar fragment in Haskell

    main = 
      let x = 3
      in let x = 4
         in print x

    $ ghc --make test.hs
    $ test
    4
Now the difference here is that each of those bindings (namings) of `x` have a context delimited by the indentation. In particular, names only have meaning within a delimited scope. In fact, the `x` bound by the inner let is completely different from the outer one. The fact that they share the same name means that the inner one shadows the outer one within the scope of the inner let.

We could demonstrate this with the following program perhaps

    main = 
      let x = 3
      in print ((let x = 4 in x) + x)

    $ ghc --make test.hs
    $ test
    7
Here we can plainly see that the context where `x` names 4 is only as large as that inner, bracketed `let ... in ...`. After we leave that scope, `x` reverts to naming 3.

The trick with figuring out FP is that it actually feels more restrictive at first. It's a typically higher-level form of expression. You can obviously simulate it all in C (FP languages might even compile down to C) but the goal is to determine what kinds of things can be expressed in the FP language itself.

To learn more, I highly suggest learning just the basics of Haskell or OCaml. Scala would probably suffice as well, though I don't know it as well to say.

Generally, the idea I'm talking about is often called "immutability" (though it's slightly different). Programming with immutable things tends to be easier to reason about because names do not change what they refer to within a context (like x changing from 3 to 4 in the C program).

Re: Teenage Haskell

#89
post #88
post #85

Earlier quoted context omitted.

I don't know, something must be wrong with my head, because I'm not any closer to understanding the point of FP. I really do want to understand it though. Your hypothetical language - is it functional? Because if it is, I don't see how it's different from C. If it's not, can you show me the equivalent code in a functional language? This is how I understand your code example: def foo (y, x): let z = get(x) assign(x, y…

The language is sort-of functional. It's as unfunctional as possible while still highlighting immutability. The key is to focus on what you can't do. Pointers in C do provide a similar UI to "boxes" that I was describing. But their plain values aren't the same. Consider int main() { int x; x = 3; x = 4; printf("x = %i\n", x); } $ gcc test.c -o test $ test x = 4 Here, I am still able to treat the value `x` as a "box"…

Having different variables under the same name, especially when we have to keep track of which is which (different values in different contexts, defined by indentation) does not sound like a good idea to me.

For example, here's a problem I had in C when I used a local variable with the same name as a global variable: http://stackoverflow.com/questions/19214293/unable-to-modify...

You're saying: "immutable things tends to be easier to reason about because names do not change what they refer to within a context" Can you please provide an example of that? Maybe some code where this 'feature' is useful? Your example of let x = 3 in print ((let x = 4 in x) + x) shows what you mean, but it does not show why would I want to do that.

Thank you very much for your effort to help me understand.

Re: Teenage Haskell

#90
post #87
post #85

Earlier quoted context omitted.

I don't know, something must be wrong with my head, because I'm not any closer to understanding the point of FP. I really do want to understand it though. Your hypothetical language - is it functional? Because if it is, I don't see how it's different from C. If it's not, can you show me the equivalent code in a functional language? This is how I understand your code example: def foo (y, x): let z = get(x) assign(x, y…

Let me see if I can clarify. Imagine a (rather useless) program that prints a number. x = 5 x+=2 print x print x this prints the number 7 2 times in the 'context' definition of equality, which we'll denote using let * = ..., each of those assignments generates a context, which I'll show using indentation. let x = 5 let x = x + 2 print x print x These two programs do the same thing. However, using names as mathematica…

Your explanation helps, however, I'm starting to think FP is hard to understand due to my lack of programming experience. And this makes me wonder why would anyone in their right mind try to offer it as the first programming language to teenagers.

The different contexts you're describing look similar to the global/local variables with the same name. For example, I had this problem in C, where I defined a global var and wanted to modify it inside a function. Which failed, because a local var with the same name was created: http://stackoverflow.com/questions/19214293/unable-to-modify... So in this example, 'immutability' was precisely what I didn't want in my program.

Can you please provide a concrete example where this 'feature' is useful?

Also, you're saying "A mutable variable is an actual location in memory". What about the name of immutable variable in FP? How is it implemented? How/where its value is being stored?

Post reply on HN