cdsmith
On the one hand, this is a change whose software engineering benefit is very small. (There is a small performance advantage, but it's not significant.) It has a large aesthetic benefit, though, in that it makes the standard library have one less ugly wart. But that wart wasn't really doing anything except being ugly. Some community members have a point of view that "ugly" shouldn't matter, and that in particular, the bar for breaking changes should be very high, and far higher than wart removal.
On the other hand, this particular change should affect extremely little actual code, because defining (/=) explicitly is dumb. When it does affect code, the solution is just to delete the lines of code that are doing the dumb thing. They don't even need to be replaced, because the only reasonable behavior is already provided by the default. Just deleting the dumb code is enough.
On the OTHER other hand, even a small amount of code change can add up to a lot of dependency management work. If just one library somewhere at the leaf of a dependency tree needs it's explicit (/=) deleted, then version bounds need to be added for all upstream bodies of code to ensure that they don't try to build against the old now-broken. Changing all those version bounds across perhaps dozens of packages is far, far more work than just deleting those few lines of code. You can look at this as a broken process, but I don't think anyone has a great answer to dependency management.
So I think it's in the end kind of a coin flip between (a) it's infuriating to some people not that this specific change is being made, but that it indicates the community values aesthetics above backward compatibility, and the absence of almost any practical software engineering benefit makes this a compelling test case upon which to direct their fury, and (b) despite the tiny amount of actual code change, it's quite possible it could lead to a non-trivial amount of coordination work between libraries, and THAT is a real (and not very fun) job.
What does affect the usability of the language is when (a) the line in the sand isn't very clear from an end-user point of view [see simplified subsumption in GHC 9, for example], or (b) the line is on the wrong side of simple features [see monomorphic local bindings, for example].
I guess what I'm saying is that Idris having minimal type inference is kind of terrible, and the excuse that it's not decidable for dependent types is a flimsy one.
By contrast, a typical mainstream programming language might, say, completely neglect one or more of these communities in favor of whatever is best for commercial programmers. Particularly when, like most mainstream languages, it's mainly funded by those interests.
HMock: First Rate Mocks in Haskell
That said, it wasn't the point of the article. It's fast becoming the point of this comment thread, though, which is unfortunate.
Why I Support the Haskell Foundation
There's a variant where you run the deferred acceptance algorithm, but then only the proposees who never rejected anyone finalize their decision. All other proposees and their matched proposers split up, and the whole algorithm is run again with the unmatched participants. This time, you end up with a Pareto-optimal matching for the proposers, with respect to their stated preferences. That is, there's no possible way to make anyone happier without making someone else less happy. But it's not stable, and the algorithm is no longer strategy-proof. (In fact, one can prove that no strategy-proof algorithm can guarantee a Pareto-optimal matching!)
Another way to see this: the entire process of choosing two finalists and then having a runoff to choose an ultimate winner counts as a collective decision-making process. That there are two separate votes doesn't actually matter. By Gibbard's theorem, then, if there isn't a dictator, then the entire process is strategic. Since the chance to use strategy doesn't occur in the simple-majority final runoff, by process of elimination, it must occur in choosing the candidates who qualify for the runoff.
Contrast this to the matching problem, where the outcome is where ALL the candidates are assigned. You're allowed to have an opinion about where you are assigned. I'm allowed to have an opinion about where I am assigned. These opinions might conflict indirectly because of limited spots, but they don't conflict directly. This is very different from the election case, where if you and I have different opinions about who we want to win, those opinions are always contradictory.
(These were later edits to the article, so if you read it early on, you may not have read those parts.)
This is a fundamental problem shared by any form of exact real arithmetic with unique representations; you can always then be forced to make a choice, before emitting any information, that depends on infinite amounts of information about the operands. To solve this problem, you would need to choose a representation with redundancy. (With redundancy, equality comparison becomes harder, and it can still diverge, but you can still get approximations of the answer.)
At the same time, certain people have views that are morally abhorrent. Or, heck, even just not very interesting. It's important to NOT to shoehorn some kind of homesteading right over public attention in the name of free speech. In the past, society's way of protecting itself against this was mainly that speech was expensive, and extremists frequently lacked the money to impose themselves on others' attention. This was in some ways a horrifying way to solve the problem, since it suppressed the disadvantaged, and didn't work anyway. In any case, it's gone. Speech is no longer expensive.
What remains to see how we can regain some semblance of sanity in a world where all public communication devolves into people shouting at each other. I'm sick of living in that world. I don't particularly care whether Facebook takes down Trump's comments; they've already been heard. But I do care about notions of free speech that prevent tech companies from trying to solve the pressing social challenge of how to let people regain control over their own attention spans.
{-# LANGUAGE NoImplicitPrelude #-}
import HaskellPrelude
import CodeWorld -- for pictures, colors, etc.
The stuff from CodeWorld is still uncurried, but the rest of the language is still there.That said, uncurrying functions also has a huge benefit when it comes to understanding error messages in Haskell. I love currying in Haskell, and it's very powerful... but it's one of the features that sometimes leads to obscure or misleading errors -- especially when you leave out type signatures... which I do for the first month or two.
Yeah, the examples are a mess right now. Let me point you to a couple things: first, there's a partially complete tutorial (click the Help button) with some simple examples. Second, (and this is very early on, so please be forgiving!) there's a draft of a textbook at https://docs.google.com/document/d/1NbMtySIDNK40Bk4ImrUAE95S... So yeah, we're working very hard on fixing the documentation issues. Patience!
I don't have such a good answer about syntax. The syntax is about as good as I can make it. There is autocomplete (Ctrl-Space) for built-in function names, and brace highlighting, and I'd love to work on more features to make the programming more interactive with immediate feedback. I also wrote a simplified version of Haskell's standard library and wrote a simple post-processor to reword the more confusing error messages, in an attempt to make it easier to find and fix problems that do occur. If you have ideas or find particularly bad examples, please add a quick example at https://github.com/google/codeworld/issues/new
If this doesn't work, and you look for alternatives to teach programming to your daughter, you might consider Scratch or (if you're still into doing it with functional programming) bootstrapworld.org.
Thanks for looking!
In this particular case, the point was that I created an educational tool for teaching mathematics. It happens to involve a programming language; but the goal isn't to train computer programmers. It's to teach math. So the language used is one that lets you describe functions and quantities the same way as you would in math, and mostly avoids the need to think about a computer doing some sequence of operations.
I assume you meant something like f(t) = t?
If so, then right, if you pass in the current time as a parameter to the function, then the result can depend on it. But in Python, you don't pass in the current time. That's because "function" means something entirely different in Python.
In math, at the simplest possible level [1], a function is a set of ordered pairs, with the property that no two different ordered pairs have the same first element. That's all there is to it. So when I write f(x) = 3x - 5, that's just shorthand for saying that f is the infinite set { (0, -5), (1, -2), (2, 1), (1/2, -7/2), ...}. That's all there is to it. There's no sequences of operations, no process, etc. It's just a set of ordered pairs.
Python's functions, on the other hand, are at their core a sequence of instructions. Some of those instructions (like loops or conditionals) have other sequences of instructions as components. They share an environment, which consists of storage locations called local variables. A Python function is actually a pretty complex thing, when you get down to it.
You could model Python's functions using standard mathematics, if you play some tricks: add hidden parameters, give interpretations to the results in terms of physical effects, etc. But this just tells you that math is powerful enough to model Python functions (and, well, anything else) in terms of its much simpler ideas. It doesn't mean that those ideas are the same as the things in Python that go by the same name.
> 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.
Okay, but you're describing the process of drawing the parabola. In math, f(x) = 3x^2 + 2x + 1 isn't a process for drawing a parabola. It is a parabola. So f, here, is itself the set of ordered pairs, which make up a parabola if you treat them as points on the coordinate place. That's the basic difference.
[1] Okay, for the pedants out there, this depends on your choice of foundations. I'm assuming the standard interpretation using ZFC, but a similar point would apply if you prefer a different foundational theory.
Now, true, the syntax is much more complicated than Scheme. You can operators and precedence and all that. But while definitely complex, it is mostly consistent with math notation. I tried to teach with Scheme first (following www.bootstrapworld.org) before I created this, and I found the change in syntax from what they are used to can be a real obstacle for children. This is also consistent with the comment about MIT moving to Python, which similarly has much more complex but familiar syntax.
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 "x" might refer to something different in a different context, such as when evaluating a function with a different argument; that's the sense in which it varies.)
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, or that even gives no result at all but causes letters to appear on a nearby computer screen. Yet in C or Python, all of these things are called functions.
At first, it might seem surprising that you can do much programming without the C or Python version of functions and variables. But:
1. You can do more than you think without reassigning variables or using functions that aren't "real" functions in the sense of mathematics, and
2. Of course, in the end, all languages - including functional languages - do have a way to create boxes to store values over time, or to perform actions that make things appear on computer screens. It's just that in a functional language, these things are not the basic bread and butter tools of programming to the extent that they are in C or Python. So you have variables and functions (in the mathematical sense), and you also have other things that act like storage locations and actions, but you only use the latter when you have a real need for them.
That's the general character of the difference. There is, of course, a lot of detail that I am leaving out in a response on a web site.
The reason people were speculating about whether this would work better with people not yet accustomed to programming is that it's often thought that experience in an imperative language (like C or Python) leads you to naturally try to do things with actions and storage locations, even when it's not necessary... and then it can get frustrating and confusing to work in a language where most things are actually not done that way. There's a theory that says if you maybe learned the functional way first, you wouldn't find it as frustrating.
I'm of two minds about that. I spent a year teaching Haskell with this system (I'm the Chris Smith mentioned in the article), and I found that it's partly true that students don't get as frustrated... sometimes. But there are other cases where students naturally fall into trying to do things in imperative ways, despite not having past experience in a programming language. I actually think, computer programming aside, that this is one of the things that trip up kids in math classes. So it's not just programming languages where this comes up: a lot of teachers present math as step-by-step processes, as well. Essentially, they introduce imperative programming without the computer. This is what happens when teachers tell students that parentheses are about what to do "first", instead of about which sub-expressions are meaningful on their own. Partly, I think this is just how the human mind works, too, and it's an inherent tendency that we have to overcome to really "get" algebra and other mathematics in a deeper sense than knowing how to do specific problems. It's still frustrating, then, for kids to adapt to having to describe processes using equations and expressions, which at their core do not list things to do, but instead describe and state facts about relationships between quantities.
I still think it's an important skill to learn. Indeed, I'm a lot more interested in teaching that kind of reasoning than I am about teaching computer programming. That's why I made changes in the new CodeWorld (the site discussed in this article) that are designed to deliberately thwart students who try to think of their programs as sequences of actions, and encourage those who think in terms of compositional expressions.