Some good thoughts in here. However I feel like when I learned Haskell (which was actually my first serious foray into programming) the hard parts were not this high level functional language philosophy stuff, but rather not knowing how to appropriately use the tooling. It took me years to finally write cabal files, QuickCheck tests, Traversable instances, etc. In that regard, this guide has been immensely useful:
I've had very similar experiences. I took a Scala course on Coursera back in 2014 and at the end I realized I couldn't really write a Scala program because the course had provided all SBT files for everything...and because they enabled all sorts of functionality related to autograding, they were impenetrably complex in addition to the necessary complexity of a build tool (which requires a willingness to read a technical manual that assumes I high level of experience and sophistication).
A lot of the difficulty is that it is relatively easy for a two pizza team to have enough experience and knowledge to collectively figure out how to get all the moving parts moving more or less in the right direction at more or less the right time. For an individual, it's always going to take years to achieve the equivalent knowledge of a team after six months.
Not defending the OP but at the same time I've never approached a brand new subject and had a textbook or similar resource which walked me through it perfectly without having to look up words I did not understand or reference other materials. That is kind of just part of the process. Having subjected myself to the world of machine learning over the past several years I can tell you I constantly encountered things I did not understand, so much so that it became routine to just go look it up and move on.
> I've never approached a brand new subject and had a textbook or similar resource which walked me through it perfectly without having to look up words I did not understand or reference other materials.
Never? That sounds like you've always been taught things the hard way.
I learned about Pi by nearly the same method of Pythagoras.
Methods come first, and the words come later. Build upon the knowledge people have, don't just plop a steaming pile of high level concepts in their lap and expect them to figure it out.
I'm sorry you've never really seen that before, but it's how I see all the greats explain things.
Take for example, Novig's Lisp interpreter in Python [0], he does expect some back knowledge. But he explains the core ideas, and then each new idea introduced just expands on the previous.
If you are going to limit learning to resources perfectly catered to your level of knowledge, then you are missing out on a lot. It's really not hard to go look up a few terms.
And equally, if you delve blindly in areas where you don't have the knowledge, you're going to be seriously handicapped.
We don't teach physics to those who have never been exposed to algebra, and you can't explain the half life of uranium to someone who doesn't know what an atom is.
In practice, we can and do explain... By giving the basics.
The beginner who tries to understand the Dragon Book, will get somewhere. They will be enhanced.
But nearly as much as if they'd read Lisp In Small Pieces.
I have plenty of technical manuals on my shelves. Once, they were utterly useless. Knowledge made them tools. But a beginner can't just leap into Intel's x86 instruction manual and expect it will help, if they don't understand registers, pointers, and that a cpu has a cache.
> The | operator indicates that this is a sum type [..]
This doesn't explain what's going on; it references terminology used only by people who already know what's going on.
A pedagogical explanation would say: the | operator means "or", in that you can use multiple different constructors (separated by |) to construct the type in question (whose name is to the left of the '=' operator). For example:
data Bool = True | False
means that you can construct a value of type Bool using one of the constructors True or False.
But the constructor approach does not explain what makes a sum type a sum.
If the readers already have some background in a programming language, you could also start with e.g. a struct from an imperative language:
struct Foo {
X x;
Y y;
}
This is a so-called product type, because the number of possible values of Foo is the number of values of type X times the number of values of type Y. So if X = {Red, Green, Blue} and Y = {Light, Dark}, then this product type has 3 x 2 = 6 different values:
What if instead, we wanted to have the sum of the possible values of X and Y? In other words, where we'd have to choose between a value from X or from Y?
I agree with your approach, one suggestion: If you're using struct to introduce product, does it make sense to use union to explain sum? Although maybe that's too complicated given the need to tag it?
"Pedagogy" is the art/science to guide kids, literally speaking. First, I wasn't sure if he didn't actually mean "didactics" but then he talked about "students" so he probably just talks about "kids" of computer science.
Why are all thoughts about how to teach/promote Haskell centered on the language itself as if it were only an academic tool? If you want students to get excited about Haskell, don't make it look like an academic tool that's only useful as a didactic device in university classes on functional programming.
> "Pedagogy" is the art/science to guide kids, literally speaking. First, I wasn't sure if he didn't actually mean "didactics" but then he talked about "students" so he probably just talks about "kids" of computer science.
Literally speaking, you may be right, but who cares? "Pedagogy" means "teaching" to anyone who is seriously engaged with the topic of conversation here. Etymology is not meaning. Defining words by their etymology alone ignores history, culture, and the context of modern word use.
17 comments
[ 3.8 ms ] story [ 54.7 ms ] threadhttp://dev.stephendiehl.com/hask/
A lot of the difficulty is that it is relatively easy for a two pizza team to have enough experience and knowledge to collectively figure out how to get all the moving parts moving more or less in the right direction at more or less the right time. For an individual, it's always going to take years to achieve the equivalent knowledge of a team after six months.
This teaching opportunity is already lost. Who are you teaching to? Someone new to programming is going to be lost by the first example.
Never? That sounds like you've always been taught things the hard way.
I learned about Pi by nearly the same method of Pythagoras.
Methods come first, and the words come later. Build upon the knowledge people have, don't just plop a steaming pile of high level concepts in their lap and expect them to figure it out.
I'm sorry you've never really seen that before, but it's how I see all the greats explain things.
Take for example, Novig's Lisp interpreter in Python [0], he does expect some back knowledge. But he explains the core ideas, and then each new idea introduced just expands on the previous.
[0] http://norvig.com/lispy.html
We don't teach physics to those who have never been exposed to algebra, and you can't explain the half life of uranium to someone who doesn't know what an atom is.
In practice, we can and do explain... By giving the basics.
The beginner who tries to understand the Dragon Book, will get somewhere. They will be enhanced.
But nearly as much as if they'd read Lisp In Small Pieces.
I have plenty of technical manuals on my shelves. Once, they were utterly useless. Knowledge made them tools. But a beginner can't just leap into Intel's x86 instruction manual and expect it will help, if they don't understand registers, pointers, and that a cpu has a cache.
> The | operator indicates that this is a sum type [..]
This doesn't explain what's going on; it references terminology used only by people who already know what's going on.
A pedagogical explanation would say: the | operator means "or", in that you can use multiple different constructors (separated by |) to construct the type in question (whose name is to the left of the '=' operator). For example:
means that you can construct a value of type Bool using one of the constructors True or False.If the readers already have some background in a programming language, you could also start with e.g. a struct from an imperative language:
This is a so-called product type, because the number of possible values of Foo is the number of values of type X times the number of values of type Y. So if X = {Red, Green, Blue} and Y = {Light, Dark}, then this product type has 3 x 2 = 6 different values: What if instead, we wanted to have the sum of the possible values of X and Y? In other words, where we'd have to choose between a value from X or from Y? That's a sum type: it is a type where you can pick a value from X or Y, giving a total of 3 + 2 = 5 possible values.Then give a motivating example where one would need such a type (e.g. trees nodes) and introduce proper notation.
Why are all thoughts about how to teach/promote Haskell centered on the language itself as if it were only an academic tool? If you want students to get excited about Haskell, don't make it look like an academic tool that's only useful as a didactic device in university classes on functional programming.
Literally speaking, you may be right, but who cares? "Pedagogy" means "teaching" to anyone who is seriously engaged with the topic of conversation here. Etymology is not meaning. Defining words by their etymology alone ignores history, culture, and the context of modern word use.