Wadler's critique of SICP (1987)
cs.kent.ac.uk
cs.kent.ac.uk
As somebody who did most of the first chapter in both Haskell and Scheme, I think it's crazy for Wadler to not mention the downsides of a strict type system; it's listed only as a positive.
The main errors that I faced in writing my programs were type errors, where I knew what I wanted to do and spent upwards of several hours figuring out the magic incantations to convince the compiler to do what I wanted it to do. They were not type errors in the sense that the compiler was preventing me from making bugs, but rather type errors in the sense that I had to figure out a whole bunch of things about the type system in order to try and convince the compiler to accept my program.
There's a heavy cognitive load to programming in Haskell, and I hit many walls where I just had to Figure It Out™ before I could compile my programs.
(All this was as an experienced programmer. Maybe it would be easier for a newbie not used to dynamic languages!)
The payback for grappling with the type system is usually confidence that your program will run without silly errors (though you can still make silly errors (hello, cut-and-paste)). I'm now spending a fair bit of time in Javascript/NodeJS and Python lands and I need lots of testing to make sure that my program won't experience some silly error sometime in the future (<- perhaps this means I'm not a good dev).
I had to do the hard part, but not really gain the benefits of the type system.
I think that's pretty straightforward thing that happened with you. The same will be with Scheme if you do some chapters from Learn You A Haskell.
Also, Haskell type system is one of most logical out there. Most type systems are either build around some weak logic with many exceptions (dynamic languages, C++, Java, C#), or just build from some limited number of cases (Ada, VHDL, Verilog).
The Haskell type system incorporates a logic system (some kind of constructive logic, I think). You actually learned that logic while "fighting the compiler" and you did some of first session with "proof assistant" which Haskell compiler/interpreter is.
So I think you're complaining for nothing.
Not that I stopping you, just my thoughts. ;)
As soon as you step out of bounds, you find strange corners of the type system. It's quite a complex beast, and many of the error messages are cryptic at best.
The first two didn't asked me or my colleague about anything type system related too often. After month or so of on-off work on his project one of them finished a complex translator from CPU description into VHDL.
The one who studied Haskell without LYAH did asked us. I attribute it to complexity of program he worked on.
My experience allows me to remain confirmed that proper exposure to Haskell type system greatly lessen associated burden.
I should note that we didn't encounter many errors in our Haskell code. Much less than in code in Java or C#.
So I'm skeptical of the idea that programming education needs to be even more hardcore than Scheme and we need to use a lazy functional language instead. I think the right way to teach programming is to give students a simple procedural language (perhaps not even OO) that makes the computer do cool things, like graphics or webpages. The ones who are curious for more hardcore stuff can always discover it afterward, like I did.
I agree that C++ is a complicated language, specially when you use Boost or Tools.h++, or the even make things worse. But when you teach beginners to code in C++ and only utilize STL, I believe it would be an interesting and challenging course. Plus, in an entry level course, you only need to introduce the basics of programming, which are (in an abstract sense) general logic principles and language agnostic.
I agree that you need to teach general logic principles which are language agnostic, but if you do this in the context of C++, the beginner is bound to waste a lot of his time fighting irrelevancies in the language.
Dana S. Scott. Outline of a mathematical theory of computation. Technical Monograph PRG-2, Oxford University Computing Laboratory, Oxford, England, November 1970.
Dana Scott and Christopher Strachey. Toward a mathematical semantics for computer languages Oxford Programming Research Group Technical Monograph. PRG-6. 1971.
Gordon D. Plotkin. A Structural Approach to Operational Semantics. (1981) Tech. Rep. DAIMI FN-19, Computer Science Department, Aarhus University, Aarhus, Denmark
Intro to programming books:
Matthias Felleisen, Robert Bruce Findler, Matthew Flatt, and Shriram Krishnamurthi. How to Design Programs: An Introduction to Programming and Computing.
Daniel P. Friedman (Author), Matthias Felleisen (Author), Duane Bibby (Drawings), Gerald J. Sussman (Foreword). The Little Schemer.
Programming language principles & implementation books:
Daniel P. Friedman, Mitchell Wand, and Christopher T. Haynes. Essentials of Programming Languages.
Shriram Krishnamurthi. Programming Languages: Application and Interpretation.
Matthias Felleisen, Robby Findler, and Matthew Flatt. Semantics Engineering with PLT Redex
These are all by pretty much the same group of people (but distributed across the US: http://racket-lang.org/people.html) so the books all go together really well.
But I agree with your suggestion that C should be teached first. If anything, because C's "computational model" is very simple: you know what executes when; it encourages a more common, procedural way of thinking, and it's easy to do side effects in single-threaded C.
There was a lot of programming language research in the 1970's and 1980's that is not really used in mainstream programming languages in these days.
A good collection of this material can be found in Simon Peyton-Jones' book "The implementation of functional programming languages". Probably out of print (my uni library has one), but freely available on the net, here's the link: http://research.microsoft.com/en-us/um/people/simonpj/papers...
It's worth to note that since the Miranda days, Haskell has added type classes that can do some OO-style stuff and more, a sensible and efficient solution for IO that also works well in parallel and a kick-ass compiler and run time system.
(define (sum x) (fold + 0 x))
Writing it this way is more idiomatic Scheme, and isn't really cumbersome.I was asking more about code in the wild that uses accumulate instead of the naive recursive formulation. That's typically what we mean by idiomatic.
I see foldl often in haskell, but rarely in scheme. I'm not disagreeing that it's a great idea, just that this is how it 'would have been written'. Personally I find the naive recursive formulation plenty clear.
(and especially SICP, which inspires such a dogmatic belief in its advocates that it really ought to just be considered a religious text at this point)
Simply put, it's more than an excellent book in the world of Computer Science. It is concise, clear, straightforward and challenging. And I think a text like that deserves every interest and respect from every computer scientist.
Respects.
I would go so far as to state that it is beyond critique
No matter how excellent a book someone might think it is, that's not a healthy attitude to have, and is essentially dogamtism.
In my opinion, comp sci is (or ought to be) about computers. And the underlying hardware of nearly all Turing-complete computers is imperative: there's a CPU which executes instructions one at a time, and which can vary which future instruction is to be executed based on the results of previous ones. I get the impression that Wadler, on the contrary, regards comp sci as a branch of mathematics rather than engineering.
I've suffered at the hands of "CS is all math" profs. I was in a course that subjected a bunch of CS-101 students to this kind of thing. A whole semester of "Here's a proof that this ten line program sums some numbers correctly."
A collective "Huh?" from the class.
It became crystal clear, after nearly everyone failed the mid-term, that things were not working. The profs held a "come to Jesus" class, where they explained everything; all the proofs, all the ten line programs that added or multiplied numbers, all the assignments full of greek symbols they made us learn. That all became crystal clear, and you could see the lightbulb blink on, just above everyone's head:
/Yup, they're trying to fuck us./
[I survived this course because I wrote my own functional language interpreter, then just typed their damned calculus into it for the programming assignments. What a crock.]
I take a real dim view of teaching "mathematically pure" CS to beginning students. You don't start riding a motorcycle by doing experiments with gryroscopes in a lab; you listen to an instructor, get on the damned thing and learn to ride in a safe environment. Save mathematical purity for after you get 'em hooked.
I've heard: "Oh, but if have them program in BASIC we're doing irreperable harm!"
Horsepucky. I'd rather have an ex-BASIC hacker at my side, helping me ship, than someone who can't write a hundred line program without dragging in declarations that nobody will be able to understand a week later. The best engineers I know weren't hurt by exposure to BASIC, or assembly; they were good at everything.
I guess I'm just a greasemonkey with a keyboard.
[I love Scheme, btw. I don't get functional languages that think it's okay to ditch the programs-as-data paradigm.]
I wish I spend my time with assembly language with something more fruitful, like Coq (which was developed during my assembler-using days).
That way you cannot count only on one CPU executing instructions one by one, you have to leave engineering, you have to do some math. You have to prove the absence of deadlocks, race conditions.