in reply to Re^12: World's shortest intro to function programming
in thread Thread on Joel on software forum : "I hate Perl programmers."
Here's where I'll heartily recommend the book The Haskell School of Expression: Learning Functional Programming through Multimedia
Well. As an interim measure I read the lecture slides. From that cursory glance--that actually went at about the right pace (4 or 5 slides representing a few 10s of pages)--it does at least appear to attempt to deal with (what I term) real-world problems.
However, and here's the reason I will want to browse the book before purchasing rather buying on line, it (appears) to skips the nasty little details.
For example, the treatment of the trivial, but strongly indicative example of the unix wc program. (Which I had to type in because it doesn't come as part of the source file distribution with the book)
import System wcf :: ( Int, Int, Int ) -> String -> ( Int, Int, Int ) wcf ( cc, w, lc ) [] = ( cc, w, lc ) wcf ( cc, w, lc ) ( ' ' : xs ) = wcf( cc+1, w+1, lc ) + xs wcf ( cc, w, lc ) ( '\t' : xs ) = wcf( cc+1, w+1, lc ) + xs wcf ( cc, w, lc ) ( '\n' : xs ) = wcf( cc+1, w+1, lc+1 ) + xs wcf ( cc, w, lc ) ( x : xs ) = wcf( cc+1, w, lc ) + xs wc :: IO() wc = do name <- getLine contents <- readFile name let ( cc, w, lc ) = wcf( 0, 0, 0 ) contents putStrLn ( "The file:" ++ name ++ " has " ) putStrLn ( show cc ++ " chars " ) putStrLn ( show w ++ " words " ) putStrLn ( show lc ++ " lines." )
Compiling and running that fails because it has no main. Okay, it's off a slide, so add main = wc. Compile and I get a (500kb!) executable. Try running it--on a file with 2 lines of 30 spaces:
C:\ghc\test>wc 60sp2l.txt wc: interrupted C:\ghc\test>wc 60sp2l.txt The file:60sp2l.txt has 62 chars 62 words 2 lines. C:\ghc\test>wc p:\test\1GB.dat The file:p:\test\1GB.dat has Heap exhausted; Current maximum heap size is 268435456 bytes (256 Mb); use `+RTS -M<size>' to increase it.
Impressed? Not! Doesn't handle command line parameters. No prompt. Counts spaces and newlines as words. Can't handle a big file.
Yes. I know it's only a demo. I should be able to add a prompt easily enough:
wcf :: ( Int, Int, Int ) -> String -> ( Int, Int, Int ) wcf ( cc, w, lc ) [] = ( cc, w, lc ) wcf ( cc, w, lc ) ( ' ' : xs ) = wcf( cc+1, w+1, lc ) x +s wcf ( cc, w, lc ) ( '\t' : xs ) = wcf( cc+1, w+1, lc ) x +s wcf ( cc, w, lc ) ( '\n' : xs ) = wcf( cc+1, w+1, lc+1 ) x +s wcf ( cc, w, lc ) ( x : xs ) = wcf( cc+1, w, lc +) xs wc :: IO() wc = do putStr ( "Filename; " ) name <- getLine contents <- readFile name let ( cc, w, lc ) = wcf( 0, 0, 0 ) contents putStrLn ( "The file:" ++ name ++ " has " ) putStrLn ( show cc ++ " chars " ) putStrLn ( show w ++ " words " ) putStrLn ( show lc ++ " lines." ) main = wc
Compile:
C:\ghc\test>ghc -o wc.exe wc.hs wc.hs:9:8: Parse error in pattern
Hmmm. Informative!
So, skip the prompt, and try and get the argument from the command line. Scan the library docs. System looks promising. But there is nothing that looks like it gives me access to the commmand line? Okay, skip that. Try dealing with the "words are spaces" problem. In an imperative language I'd simple 'remember' the previous character and treat consecutive spaces (and newlines) as a single delimiter for the purpose of counting words...but of course, that's state!
So, how about dealing with the memory issue? I thought the beauty of Haskell was that it was non-strict or lazy. That it dealt with infinite lists. Then why does getContents insist on loading the whole darn file?
Another example drawn from the same source.
From Chapter 8, containsS for Rectangles is defined as:
Rectangle s1 s2 `containsS` (x,y) = let t1 = s1 / 2 t2 = s2 / 2 in -t1<=x && x<=t1 && -t2<=y && t2<=t2
But there is a classical GUI problem here. If you divide the screen into a grid, of say 10 x 10 pixels, then by the above definition any point on the right edge of one rectangle also appears on the left edge of the adjacent rectangle to its right. Likewise for points on the other three edges and their corresponding neighbours. This leaves a point at the crossroads between 4 adjacent squares testing as being contained within all four squares simultaneously! Might work for a Corner bet in roulette, but it surely doesn't work well for the majority of hit-testing purposes in graphical applications.
And that's the problem. All the demos are the same. They concentrate on (laborious formal) examination of Haskell's strengths and completely skip over all the messy edge cases.
All languages have their strengths and weaknesses. What defines a languages usability is the way in which it deals with it's weaknesses. What puts the P in Perl, is the practical way in which it has built-in mechanisms for dealing with the messiness of the real world--the edge cases--even where that means it has to eshew orthoganality and purity in order to achieve that practicality. Where the same problem in usability crops up frequently, the language has been extended and "special cased" to deal with that situation in a reasonable and usually quite intuative way. And the special cases are the subject of extensive documentation in the FAQ.
My problem with trying to get to grips with FP is that the FP language documentation reflects their theoretical origins by expounding on the formalism of their definitions extensively, but (from what I've seen so far) leaving the messy detail of dealing with the edge cases to .... I don't know yet. I haven't found the answer.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^14: World's shortest intro to function programming
by Anonymous Monk on Jun 20, 2005 at 15:46 UTC | |
by BrowserUk (Patriarch) on Jun 20, 2005 at 19:38 UTC | |
by Anonymous Monk on Jun 20, 2005 at 20:07 UTC | |
by kelan (Deacon) on Jun 21, 2005 at 14:44 UTC | |
by BrowserUk (Patriarch) on Jun 21, 2005 at 20:17 UTC | |
by Anonymous Monk on Jun 20, 2005 at 20:49 UTC | |
|
Re^14: World's shortest intro to function programming
by kelan (Deacon) on Jun 21, 2005 at 19:45 UTC | |
by BrowserUk (Patriarch) on Jun 21, 2005 at 20:11 UTC |