Thread overview | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 25, 2012 Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
I've often heard that claim, but here's an article with what the substance is: http://dubhrosa.blogspot.co.uk/2012/12/lessons-learning-haskell.html?m=1 Note that D offers this style of programming, with checkable purity, immutability and ranges. I think it is a very important paradigm. |
December 25, 2012 Re: Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Tuesday, 25 December 2012 at 19:37:42 UTC, Walter Bright wrote:
> I've often heard that claim, but here's an article with what the substance is:
>
> http://dubhrosa.blogspot.co.uk/2012/12/lessons-learning-haskell.html?m=1
>
> Note that D offers this style of programming, with checkable purity, immutability and ranges. I think it is a very important paradigm.
I think you missed a big part here, the by default of purity. It is in D more work to enforce purity of functions then not.
The other part he talked about is countered in the language (as well to a worrying degree in Phobos) with function returns of type auto.
Taking his example:
foo :: Map Integer String -> String -> auto
Even if the function always returns integer it only requires one function to not do that and you would start second guessing every function returning auto.
Cheers, Jakob.
|
December 25, 2012 Re: Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Tuesday, 25 December 2012 at 19:37:42 UTC, Walter Bright wrote:
> I've often heard that claim, but here's an article with what the substance is:
>
> http://dubhrosa.blogspot.co.uk/2012/12/lessons-learning-haskell.html?m=1
>
> Note that D offers this style of programming, with checkable purity, immutability and ranges. I think it is a very important paradigm.
Same is often said for lisp for (IMO) far far better reasons, but it is still pure nonsense. In my case, the more i learn lisp more i hate c++, and since i have to use it, i become frustrated and unproductive. C++ made me develop a hatred to the languages that get in your way for absolutely no reason (example: lack of static if) or locks you to certain paradigms (single for Haskell?).
I am reading the book "Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp", and i have to say it was somewhat a shocking experience. The fact that in a popular book about the highest level language which includes chapters for writing interpreters, compilers, yet i haven't met a c/c++ book including such things, it is said these languages are one of the low level languages. I know it is much easier to write those for lisp than C, yet try to understand my point.
Sorry for being a lisp advocate in D forum, but you know i am on your side, we all are (i hope) trying to find the best tool for the job.
|
December 25, 2012 Re: Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
Posted in reply to so | On Tuesday, 25 December 2012 at 20:29:54 UTC, so wrote:
>
> I am reading the book "Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp", and i have to say it was somewhat a shocking experience. The fact that in a popular book about the highest level language which includes chapters for writing interpreters, compilers, yet i haven't met a c/c++ book including such things, it is said these languages are one of the low level languages. I know it is much easier to write those for lisp than C, yet try to understand my point.
>
SICP also leads the student from the very basics all the way to the writing of a Scheme interpreter and a compiler in Scheme. That would probably not be possible in a reasonable number of pages for a language with a more complex syntax. Anyway, that doesn't mean that it's not possible, it's just take a whole lot more effort to do the same in C++ or in D.
As for being a better programmer after having used some advanced concepts, I don't know. I think every feature of a language must be used where appropriate. I've seen some Python code using heavily map/filter/etc that was simply unreadable to me. In some places, I find it easier to understand for loops, while in other cases, using functional style programming conveys the intent better. But maybe that's just me.
|
December 25, 2012 Re: Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Tuesday, December 25, 2012 11:37:42 Walter Bright wrote:
> I've often heard that claim, but here's an article with what the substance is:
>
> http://dubhrosa.blogspot.co.uk/2012/12/lessons-learning-haskell.html?m=1
>
> Note that D offers this style of programming, with checkable purity, immutability and ranges. I think it is a very important paradigm.
I totally agree that learning a functional language makes you a better programmer, and I think that it's awesome that we can program that way in D. However, to actually really gain the benefit in terms of learning, you probably have to actually program in a functional language, because you're _forced_ to learn how to program in a functional paradigm, whereas in D it's only an option for when you want to do so. And Haskell is a particularly good language for it, because its laziness forces it to be pretty much purely functional whereas a number of other functional languages have more back doors to imperative programming and mutation.
Either way, it's great that D allows us to program in such paradigms.
- Jonathan M Davis
|
December 25, 2012 Re: Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jakob Bornecrantz | On 12/25/2012 11:57 AM, Jakob Bornecrantz wrote: > On Tuesday, 25 December 2012 at 19:37:42 UTC, Walter Bright wrote: >> Note that D offers this style of programming, with checkable purity, >> immutability and ranges. I think it is a very important paradigm. > I think you missed a big part here, the by default of purity. It is in D more > work to enforce purity of functions then not. I think optional purity is pretty powerful. You can have the advantages of either, at your choice. > The other part he talked about is countered in the language (as well to a > worrying degree in Phobos) with function returns of type auto. > > Taking his example: > foo :: Map Integer String -> String -> auto > > Even if the function always returns integer it only requires one function to not > do that and you would start second guessing every function returning auto. Nobody makes you use auto, either. |
December 25, 2012 Re: Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 12/26/2012 12:11 AM, Walter Bright wrote:
> I think optional purity is pretty powerful. You can have the advantages of
> either, at your choice.
True, but there's a difference between what's useful when building an application, and what's useful as a learning exercise.
|
December 25, 2012 Re: Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | (In the end this answer has become a little article.) Walter: Being a "good programmer" means having a quite long list of different skills and qualities. I think that learning Haskell helps you improve, but only in a small percentage of those skills. So I think overall Haskell doesn't make a large difference (despite since many months I have started to study Haskell). Regarding D, it's very different from Haskell, and I think it's very hard to learn from D what you can learn from Haskell. Haskell is single-paradigm and almost forces you to program in certain different ways. From that little blog post: >It forced me to think of every such problem as a chain of the primitive list operations, maps, folds, filters and scans. Now I always think in these terms. I "see" the transformation of a container as a simple sequence of these operations.< Decomposing part of the code in terms of such higher order functions is sometimes a good idea that makes the code cleaner and frees the mind to think at a higher level. Python goes one step further with its list comps that make the code even more readable, removing map and filters (list comps are available in Haskell too, but the syntax is a little worse, and probably for cultural reasons it's used less than in Python): foos = (x * x for x in items if x % 2) In D you have to use map and filter to do the same thing, and it's more noisy, less readable and longer: auto foos = items.filter!(x => x % 2)().map!(x => x * x)(); In Haskell sometimes you define an inner recursive function (sometimes named "go") where in D/Python you just use a loop. The loop doesn't risk blowing the stack (especially in Python), is often equally shorter to write, and in many situations I keep finding loops more readable and cleaner than recursion. So on one hand you have C code that contains lot of hairy nested loops with twiddly pointer arithmetic, that shows you the details of how something is done, but it doesn't tell you why. To understand such C code you have to make a summary of the code in your head, and build a bit higher view of what is done (from an older version of http://rosettacode.org/wiki/Topswops ): #include <stdio.h> #include <string.h> typedef struct { char v[16]; } deck; int n, d, best[16]; void tryswaps(deck *a, int f, int s) { int i, j, k; deck b = *a; if (d > best[n]) best[n] = d; for (i = 0, k = 1 << s; k >>= 1, --s; ) { if (a->v[s] == -1 || a->v[s] == s) break; i |= k; if ((i & f) == i && d + best[s] < best[n]) return; } s++, d++; for (i = 1, k = 2; i < s; i++, k <<= 1) { if (b.v[i] == -1) { if (f & k) continue; } else if (b.v[i] != i) continue; b.v[0] = j = i; while (j--) b.v[i-j] = a->v[j]; tryswaps(&b, f|k, s); } d--; } int main(void) { deck x; memset(&x, -1, sizeof(x)); x.v[0] = 0; for (n = 1; n <= 12; n++) { best[n] = d = 0; tryswaps(&x, 1, n); printf("%2d: %d\n", n, best[n]); } return 0; } A short Haskell solution is shorter, and much cleaner/nicer if you know a little of Haskell (but also much slower, possibly ten times slower or more): import Data.List (permutations) topswops :: Int -> Int topswops n = foldl max 0 $ map topswops' $ permutations [1..n] topswops' :: [Int] -> Int topswops' xa@(1:_) = 0 topswops' xa@(x:_) = 1 + topswops' reordered where reordered = reverse (take x xa) ++ drop x xa main = mapM_ (\x -> putStrLn $ show x ++ ":\t" ++ show (topswops x)) [1..10] On the other hand Haskell code sometimes contains tens of tiny functions that requires you a elephant-grade long term memory (even if you are using an Haskell IDE) to remember the meaning of all those functions and several 3-4-symbol-long operators, plus it asks you a large medium-term memory to keep in mind how those numerous little functions are plugged together in complex ways to produce the results. So while I've seen both very good C and good Haskell code, in both languages it's possible to write code that requires lot of brainpower to be understood. I have found that good D code is a good middle point between those kinds of C and Haskell coding: it calls and uses a moderate amount of functions, it often uses a very limited amount of pointers, its loops usually are clean and at worst use slices instead of pointer arithmetic. And micropatterns like map and filter are available in D, but also normal loops are available to avoid recursion. Immutability is available. The end result is a kind of D code that for me avoids the problems visible in both that C and Haskell code. This is why I often use D instead of Haskell or C. (I have not yet studied Scala, maybe it offers similar qualities as D or maybe even better, despite on the JavaVM it often doesn't allow you to specify with enough precision the layout of the data structures in memory). This is a modified D version of the C code (it's not exactly equal), and for me it's significantly more clean than that C code: import std.algorithm, std.range; uint topswops(in uint n) nothrow in { assert(n > 0 && n < 32); } body { static uint[32] best; alias T = byte; alias Deck = T[best.length]; void trySwaps(in ref Deck deck, in uint f, in uint d) nothrow { if (d > best[n]) best[n] = d; foreach_reverse (i; 0 .. n) { if (deck[i] == -1 || deck[i] == i) break; if (d + best[i] <= best[n]) return; } Deck deck2 = deck; foreach (i; 1 .. n) { immutable uint k = 1U << i; if (deck2[i] == -1) { if (f & k) continue; } else if (deck2[i] != i) continue; deck2[0] = cast(T)i; foreach_reverse (j; 0 .. i) deck2[i - j] = deck[j]; // Reverse copy. trySwaps(deck2, f | k, d + 1); } } best[n] = 0; Deck deck0 = -1; deck0[0] = 0; trySwaps(deck0, 1, 0); return best[n]; } void main() { import std.stdio; foreach (i; 1 .. 12) writefln("%2d: %d", i, topswops(i)); } Using templates you can make that D code about twice faster. That D code is still low-level, it contains a static variable, but still that code is much simpler to understand compared to that C code. In that D code this is an alternative way to write the reverse copy, but unfortunately here you have to pay some abstraction penalty, because using DMD this makes the code significantly slower (in Phobos "copyTo" is named "copy" but I prefer "copyTo" to remind me what the source and destination are!): deck[0 .. i].copyTo(deck2[1 .. i + 1].retro()); That D code is quite "algorithmic" and designed for speed. If you care less for performance it's easy to write higher level D code that's shorter and easy to understand: import std.stdio, std.algorithm, std.range, permutations2; uint topswops(in uint n) in { assert (n > 0 && n < 32); } body { static uint flip(uint[] deck) pure nothrow { uint[32] temp = void; temp[0 .. deck.length] = deck[]; uint count = 0; for (auto t0 = temp[0]; t0; t0 = temp[0]) { temp[0 .. t0 + 1].reverse(); // Slow with DMD. count++; } return count; } return iota(n).array().permutations!0().map!flip().reduce!max(); } void main() { foreach (i; 1 .. 11) writefln("%2d: %d", i, topswops(i)); } There are ways to write this D code in an even a little simpler way to understand, producing a little longer (less packed) code. On the other hand D is not perfect, and there are always bad parts or things to improve in everything. The lack of a "yield" as in Python makes many D coding patterns less handy (and the lack of list comps makes the D code a little less readable, but this is less important). The lazy lists of Haskell (also present in some form in Perl6 and Scala) offer some handy coding patterns, that are rather harder to use in D. The lack of good subtyping makes D code less strong (I have discussed it some times, like here http://forum.dlang.org/thread/pxnyniryvdwpdxoymuau@forum.dlang.org ). In D sometimes the creation of immutable data structures is not handy. I have discussed this in two or more past posts. If you compare Haskell with D, the use and management of the Maybe Haskell type is much better than the Nullable of Phobos, because of D lack of both pattern matching and of a bit of typestate (that should allow D to know that in the "else" branch of a not-null test of a Nullable with isNull, the type is not null, it can't throw an exception and it can be used safely). Some of such things should be improved in D language and Phobos, where possible. -------------------- SomeDude: >I've seen some Python code using heavily map/filter/etc that was simply unreadable to me.< Pythonic code does not contain many map/filter (Pythonic code uses lazy or eager list comps). So probably that was bad Python code, or at least not pythonic. Bye, bearophile |
December 26, 2012 Re: Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
Posted in reply to SomeDude | On Tuesday, 25 December 2012 at 20:50:35 UTC, SomeDude wrote:
> As for being a better programmer after having used some advanced concepts, I don't know. I think every feature of a language must be used where appropriate. I've seen some Python code using heavily map/filter/etc that was simply unreadable to me. In some places, I find it easier to understand for loops, while in other cases, using functional style programming conveys the intent better. But maybe that's just me.
I didn't know "set -o vi" until a few weeks ago, learning it made me a better linux user as i knew both vi and terminal. but it didn't make me a better pc user generally. If my environment doesn't evolve with me or lack tools to combine to make something new (probably i'm repeating myself) than i gain nothing from learning a feature of another language.
IMO, learning programming language X doesn't make you a better programmer. Learning X make you better X programmer. But if your existing environment/language is extremely flexible, takes code generation *very* seriously, you have a case. You gain something from learning a new feature or a paradigm. That is why lisp fascinates me, as i believe code generation is one of the most important (if not the most important) thing in a PL.
|
December 26, 2012 OT: Re: Learning Haskell makes you a better programmer? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 12/25/2012 11:37 AM, Walter Bright wrote: > http://dubhrosa.blogspot.co.uk/2012/12/lessons-learning-haskell.html?m=1 I think I am being a troll but that page is dark white on white! Ali |
Copyright © 1999-2021 by the D Language Foundation