\FOT{2}\Seq% {\def\HeadingLevel% {0}\def\PageNumberFormat% {1}\def\PageNumberRestart% {0}\def\PageNColumns% {1}\def\PageColumnSep% {36\p@}\def\PageBalanceColumns% {0}\def\WritingMode% {lefttoright}\def\InputWhitespaceTreatment% {collapse}\def\LeftMargin% {72\p@}\def\RightMargin% {72\p@}\def\PageWidth% {612\p@}\def\PageHeight% {792\p@}\def\MinLeading% {2\p@}\def\MinLeadingFactor% {0}\def\TopMargin% {72\p@}\def\BottomMargin% {96\p@}\def\HeaderMargin% {48\p@}\def\FooterMargin% {48\p@}}\Node% {}\Node% {\def\Label% {HASKELL.V8}}\Seq% {}\SpS% {\def\PageNColumns% {1}\def\InputWhitespaceTreatment% {collapse}\def\fSize% {10\p@}\def\fWeight% {medium}\def\fPosture% {upright}\def\fFamName{Times-New-Roman}\def\LineSpacing% {13\p@}\def\LineSpacingFactor% {0}} \SpSOtherBackLeftFooter% {} \SpSOtherBackLeftHeader% {} \SpSOtherBackCenterFooter% {} \SpSOtherBackCenterHeader% {} \SpSOtherBackRightFooter% {} \SpSOtherBackRightHeader% {} \SpSFirstBackLeftFooter% {} \SpSFirstBackLeftHeader% {} \SpSFirstBackCenterFooter% {} \SpSFirstBackCenterHeader% {} \SpSFirstBackRightFooter% {} \SpSFirstBackRightHeader% {} \SpSOtherFrontLeftFooter% {} \SpSOtherFrontLeftHeader% {} \SpSOtherFrontCenterFooter% {} \SpSOtherFrontCenterHeader% {} \SpSOtherFrontRightFooter% {} \SpSOtherFrontRightHeader% {} \SpSFirstFrontLeftFooter% {} \SpSFirstFrontLeftHeader% {} \SpSFirstFrontCenterFooter% {} \SpSFirstFrontCenterHeader% {} \SpSFirstFrontRightFooter% {} \SpSFirstFrontRightHeader% {}\Seq% {}\Par% {\def\LineSpacing% {1\p@}\def\LineSpacingFactor% {0}}\endPar{}\Seq% {}\Node% {\def\Element% {2}\def\ProcessingMode% {book-titlepage-recto-mode}}\Par% {\def\fSize% {24.883\p@}\def\LineSpacing% {32.348\p@}\def\LineSpacingFactor% {0}\def\Quadding% {center}\def\HeadingLevel% {1}\def\fFamName{Arial}\def\fWeight% {bold}\def\sbNom% {18.662\p@}\def\sbMin% {18.662\p@}\def\sbMax% {18.662\p@}\def\sbConditional% {1}\def\KeepWithNext% {1}}Haskell on All Eight Cylinders\endPar{}\endNode{}\Seq% {}\Par% {\def\saNom% {99.533\p@}\def\saMin% {99.533\p@}\def\saMax% {99.533\p@}\def\saConditional% {1}} \endPar{}\Node% {\def\Element% {3}\def\ProcessingMode% {book-titlepage-recto-mode}}\Seq% {}\Par% {\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\Quadding% {center}\def\fFamName{Arial}\def\fWeight% {bold}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\KeepWithNext% {1}}John Goerzen\endPar{}\endSeq{}\endNode{}\endSeq{}\endSeq{}\endSeq{}\DisplayGroup% {\def\BreakBefore% {page}}\Seq% {}\Par% {\def\LineSpacing% {1\p@}\def\LineSpacingFactor% {0}}\endPar{}\Seq% {}\Node% {\def\Element% {2}\def\ProcessingMode% {book-titlepage-verso-mode}}\Seq% {\def\fFamName{Arial}\def\fWeight% {bold}}Haskell on All Eight Cylinders\endSeq{}\endNode{}\Seq% {}\Node% {\def\Element% {3}\def\ProcessingMode% {book-titlepage-verso-mode}}\Par% {\def\saNom% {13\p@}\def\saMin% {13\p@}\def\saMax% {13\p@}\def\saConditional% {1}}\Seq% {}by John Goerzen\endSeq{}\endPar{}\endNode{}\Seq% {}\Node% {\def\Element% {6}\def\ProcessingMode% {book-titlepage-verso-mode}}\DisplayGroup% {\def\fFamName{Times-New-Roman}}\DisplayGroup% {\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Node% {\def\Element% {7}\def\ProcessingMode% {book-titlepage-verso-mode}}\Par% {\def\fSize% {8\p@}\def\fFamName{Times-New-Roman}}Copyright (C) 2004 John Goerzen. All rights reserved. Redistribution in whole or part is prohibited.\endPar{}\endNode{}\endDisplayGroup{}\endDisplayGroup{}\endNode{}\endSeq{}\endSeq{}\endSeq{}\endSeq{}\endDisplayGroup{}\endSpS{}\SpS% {\def\PageNColumns% {1}\def\PageNumberFormat% {i}\def\InputWhitespaceTreatment% {collapse}\def\fSize% {10\p@}\def\fWeight% {medium}\def\fPosture% {upright}\def\fFamName{Times-New-Roman}\def\LineSpacing% {13\p@}\def\LineSpacingFactor% {0}} \SpSOtherBackLeftFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherBackLeftHeader% {} \SpSOtherBackCenterFooter% {} \SpSOtherBackCenterHeader% {} \SpSOtherBackRightFooter% {} \SpSOtherBackRightHeader% {} \SpSFirstBackLeftFooter% {} \SpSFirstBackLeftHeader% {} \SpSFirstBackCenterFooter% {} \SpSFirstBackCenterHeader% {} \SpSFirstBackRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstBackRightHeader% {} \SpSOtherFrontLeftFooter% {} \SpSOtherFrontLeftHeader% {} \SpSOtherFrontCenterFooter% {} \SpSOtherFrontCenterHeader% {} \SpSOtherFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherFrontRightHeader% {} \SpSFirstFrontLeftFooter% {} \SpSFirstFrontLeftHeader% {} \SpSFirstFrontCenterFooter% {} \SpSFirstFrontCenterHeader% {} \SpSFirstFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstFrontRightHeader% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fSize% {20.736\p@}\def\LineSpacing% {26.957\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {1}\def\sbNom% {15.552\p@}\def\sbMin% {15.552\p@}\def\sbMax% {15.552\p@}\def\sbConditional% {1}\def\saNom% {10.368\p@}\def\saMin% {10.368\p@}\def\saMax% {10.368\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}Table of Contents\endPar{}\Par% {\def\StartIndent% {72\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {bold}\def\Quadding% {start}\def\sbNom% {2.4\p@}\def\sbMin% {2.4\p@}\def\sbMax% {2.4\p@}\def\sbConditional% {1}\def\saNom% {2.4\p@}\def\saMin% {2.4\p@}\def\saMax% {2.4\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Link% {\def\Label% {FREEDOM}}\Seq% {}\Seq% {}\Seq% {}1\endSeq{}. \endSeq{}\Node% {\def\Element% {9}\def\ProcessingMode% {title-sosofo-mode}}Freedom\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Label% {FREEDOM}}\Seq% {}\Node% {\def\Label% {FREEDOM}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Label% {FREEDOM}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Seq% {}\Par% {\def\StartIndent% {96\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Label% {THE.1971.NOVA}}\Seq% {}\Node% {\def\Element% {27}\def\ProcessingMode% {title-sosofo-mode}}The 1971 Nova\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Label% {THE.1971.NOVA}}\Seq% {}\Node% {\def\Label% {THE.1971.NOVA}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Label% {THE.1971.NOVA}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\endSeq{}\Par% {\def\StartIndent% {72\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {bold}\def\Quadding% {start}\def\sbNom% {2.4\p@}\def\sbMin% {2.4\p@}\def\sbMax% {2.4\p@}\def\sbConditional% {1}\def\saNom% {2.4\p@}\def\saMin% {2.4\p@}\def\saMax% {2.4\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Link% {\def\Label% {GETTING.ACQUAINTED}}\Seq% {}\Seq% {}\Seq% {}2\endSeq{}. \endSeq{}\Node% {\def\Element% {38}\def\ProcessingMode% {title-sosofo-mode}}Getting Acquainted\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Label% {GETTING.ACQUAINTED}}\Seq% {}\Node% {\def\Label% {GETTING.ACQUAINTED}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Label% {GETTING.ACQUAINTED}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {72\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {bold}\def\Quadding% {start}\def\sbNom% {2.4\p@}\def\sbMin% {2.4\p@}\def\sbMax% {2.4\p@}\def\sbConditional% {1}\def\saNom% {2.4\p@}\def\saMin% {2.4\p@}\def\saMax% {2.4\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Link% {\def\Label% {THE.ENGINE}}\Seq% {}\Seq% {}\Seq% {}3\endSeq{}. \endSeq{}\Node% {\def\Element% {58}\def\ProcessingMode% {title-sosofo-mode}}The Engine\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Label% {THE.ENGINE}}\Seq% {}\Node% {\def\Label% {THE.ENGINE}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Label% {THE.ENGINE}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Seq% {}\Par% {\def\StartIndent% {96\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Label% {NATURE.OF.HASKELL}}\Seq% {}\Node% {\def\Element% {64}\def\ProcessingMode% {title-sosofo-mode}}The Nature of Haskell\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Label% {NATURE.OF.HASKELL}}\Seq% {}\Node% {\def\Label% {NATURE.OF.HASKELL}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Label% {NATURE.OF.HASKELL}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {96\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Label% {TEST.DRIVE}}\Seq% {}\Node% {\def\Element% {87}\def\ProcessingMode% {title-sosofo-mode}}Test Drive\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Label% {TEST.DRIVE}}\Seq% {}\Node% {\def\Label% {TEST.DRIVE}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Label% {TEST.DRIVE}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Seq% {}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {93}}\Seq% {}\Node% {\def\Element% {94}\def\ProcessingMode% {title-sosofo-mode}}An Imperative grep\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {93}}\Seq% {}\Node% {\def\Element% {93}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {93}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {102}}\Seq% {}\Node% {\def\Element% {103}\def\ProcessingMode% {title-sosofo-mode}}A Haskell grep\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {102}}\Seq% {}\Node% {\def\Element% {102}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {102}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {109}}\Seq% {}\Node% {\def\Element% {110}\def\ProcessingMode% {title-sosofo-mode}}Compiling grep\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {109}}\Seq% {}\Node% {\def\Element% {109}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {109}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {117}}\Seq% {}\Node% {\def\Element% {118}\def\ProcessingMode% {title-sosofo-mode}}What grep Tells Us About The World\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {117}}\Seq% {}\Node% {\def\Element% {117}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {117}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {136}}\Seq% {}\Node% {\def\Element% {137}\def\ProcessingMode% {title-sosofo-mode}}Analyzing Haskell grep\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {136}}\Seq% {}\Node% {\def\Element% {136}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {136}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {152}}\Seq% {}\Node% {\def\Element% {153}\def\ProcessingMode% {title-sosofo-mode}}A New, Expanded Haskell grep\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {152}}\Seq% {}\Node% {\def\Element% {152}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {152}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {195}}\Seq% {}\Node% {\def\Element% {196}\def\ProcessingMode% {title-sosofo-mode}}Haskell grep Broken Down\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {195}}\Seq% {}\Node% {\def\Element% {195}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {195}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\endSeq{}\Par% {\def\StartIndent% {96\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {224}}\Seq% {}\Node% {\def\Element% {225}\def\ProcessingMode% {title-sosofo-mode}}Test Drive Results\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {224}}\Seq% {}\Node% {\def\Element% {224}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {224}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\endSeq{}\Par% {\def\StartIndent% {72\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {bold}\def\Quadding% {start}\def\sbNom% {2.4\p@}\def\sbMin% {2.4\p@}\def\sbMax% {2.4\p@}\def\sbConditional% {1}\def\saNom% {2.4\p@}\def\saMin% {2.4\p@}\def\saMax% {2.4\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Link% {\def\Label% {SAFETY}}\Seq% {}\Seq% {}\Seq% {}4\endSeq{}. \endSeq{}\Node% {\def\Element% {235}\def\ProcessingMode% {title-sosofo-mode}}Safety Belts: The Type System\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Label% {SAFETY}}\Seq% {}\Node% {\def\Label% {SAFETY}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Label% {SAFETY}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Seq% {}\Par% {\def\StartIndent% {96\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {238}}\Seq% {}\Node% {\def\Element% {239}\def\ProcessingMode% {title-sosofo-mode}}A Brief Typing Backgrounder\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {238}}\Seq% {}\Node% {\def\Element% {238}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {238}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Seq% {}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {242}}\Seq% {}\Node% {\def\Element% {243}\def\ProcessingMode% {title-sosofo-mode}}Strong vs. Weak Typing\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {242}}\Seq% {}\Node% {\def\Element% {242}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {242}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {250}}\Seq% {}\Node% {\def\Element% {251}\def\ProcessingMode% {title-sosofo-mode}}Static vs. Dynamic Checking\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {250}}\Seq% {}\Node% {\def\Element% {250}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {250}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\endSeq{}\Par% {\def\StartIndent% {96\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {258}}\Seq% {}\Node% {\def\Element% {259}\def\ProcessingMode% {title-sosofo-mode}}Overview of Haskell's Type System\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {258}}\Seq% {}\Node% {\def\Element% {258}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {258}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Seq% {}\Par% {\def\StartIndent% {120\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {265}}\Seq% {}\Node% {\def\Element% {266}\def\ProcessingMode% {title-sosofo-mode}}Type Inference\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {265}}\Seq% {}\Node% {\def\Element% {265}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {265}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\endSeq{}\Par% {\def\StartIndent% {96\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {288}}\Seq% {}\Node% {\def\Element% {289}\def\ProcessingMode% {title-sosofo-mode}}Some Quick Experiments with ghci\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {288}}\Seq% {}\Node% {\def\Element% {288}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {288}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Par% {\def\StartIndent% {96\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {322}}\Seq% {}\Node% {\def\Element% {323}\def\ProcessingMode% {title-sosofo-mode}}Some Typing Experiments with ghci\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {322}}\Seq% {}\Node% {\def\Element% {322}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {322}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\endSeq{}\Par% {\def\StartIndent% {72\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {bold}\def\Quadding% {start}\def\sbNom% {2.4\p@}\def\sbMin% {2.4\p@}\def\sbMax% {2.4\p@}\def\sbConditional% {1}\def\saNom% {2.4\p@}\def\saMin% {2.4\p@}\def\saMax% {2.4\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Link% {\def\Label% {FUEL}}\Seq% {}\Seq% {}\Seq% {}5\endSeq{}. \endSeq{}\Node% {\def\Element% {335}\def\ProcessingMode% {title-sosofo-mode}}The Fuel: Functions\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Label% {FUEL}}\Seq% {}\Node% {\def\Label% {FUEL}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Label% {FUEL}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\Seq% {}\Par% {\def\StartIndent% {96\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {medium}\def\Quadding% {start}}\Link% {\def\Element% {338}}\Seq% {}\Node% {\def\Element% {339}\def\ProcessingMode% {title-sosofo-mode}}Our Functions Actually Do Something\endNode{}\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Element% {338}}\Seq% {}\Node% {\def\Element% {338}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Element% {338}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\endSeq{}\Par% {\def\StartIndent% {72\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-24\p@}\def\FirstLineStartIndentFactor% {0}\def\fWeight% {bold}\def\Quadding% {start}\def\sbNom% {2.4\p@}\def\sbMin% {2.4\p@}\def\sbMax% {2.4\p@}\def\sbConditional% {1}\def\saNom% {2.4\p@}\def\saMin% {2.4\p@}\def\saMax% {2.4\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Link% {\def\Label% {CH.INDEX}}\Seq% {}Index\endSeq{}\endLink{}\Seq% {}\Leader% {}.\endLeader{}\Link% {\def\Label% {CH.INDEX}}\Seq% {}\Node% {\def\Label% {CH.INDEX}\def\ProcessingMode% {toc-page-number-mode}}\insertCurrentNodePageNumber% {\def\Label% {CH.INDEX}}\endNode{}\endSeq{}\endLink{}\endSeq{}\endPar{}\endSeq{}\endSpS{}\Node% {\def\Element% {1}}\endNode{}\Node% {\def\Label% {FREEDOM}}\SpS% {\def\PageNColumns% {1}\def\PageNumberRestart% {1}\def\PageNumberFormat% {1}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\InputWhitespaceTreatment% {collapse}\def\Quadding% {start}\def\fSize% {10\p@}\def\fWeight% {medium}\def\fPosture% {upright}\def\fFamName{Times-New-Roman}\def\LineSpacing% {13\p@}\def\LineSpacingFactor% {0}} \SpSOtherBackLeftFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherBackLeftHeader% {\Seq% {\def\fPosture% {italic}}\Node% {\def\Element% {9}\def\ProcessingMode% {hf-mode}}\Seq% {}Chapter 1. Freedom\endSeq{}\endNode{}\endSeq{}} \SpSOtherBackCenterFooter% {} \SpSOtherBackCenterHeader% {} \SpSOtherBackRightFooter% {} \SpSOtherBackRightHeader% {} \SpSFirstBackLeftFooter% {} \SpSFirstBackLeftHeader% {} \SpSFirstBackCenterFooter% {} \SpSFirstBackCenterHeader% {} \SpSFirstBackRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstBackRightHeader% {} \SpSOtherFrontLeftFooter% {} \SpSOtherFrontLeftHeader% {} \SpSOtherFrontCenterFooter% {} \SpSOtherFrontCenterHeader% {} \SpSOtherFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherFrontRightHeader% {\Seq% {\def\fPosture% {italic}}\Node% {\def\Element% {9}\def\ProcessingMode% {hf-mode}}\Seq% {}Chapter 1. Freedom\endSeq{}\endNode{}\endSeq{}} \SpSFirstFrontLeftFooter% {} \SpSFirstFrontLeftHeader% {} \SpSFirstFrontCenterFooter% {} \SpSFirstFrontCenterHeader% {} \SpSFirstFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstFrontRightHeader% {}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fSize% {20.736\p@}\def\LineSpacing% {26.957\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {1}\def\sbNom% {15.552\p@}\def\sbMin% {15.552\p@}\def\sbMax% {15.552\p@}\def\sbConditional% {1}\def\KeepWithNext% {1}}Chapter 1. \Seq% {}\Node% {\def\Element% {9}\def\ProcessingMode% {component-title-mode}}Freedom\endNode{}\endSeq{}\endPar{}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {italic}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\sbNom% {6.48\p@}\def\sbMin% {6.48\p@}\def\sbMax% {6.48\p@}\def\sbConditional% {1}\def\saNom% {10.368\p@}\def\saMin% {10.368\p@}\def\saMax% {10.368\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Seq% {}\endSeq{}\endPar{}\endSeq{}\Node% {\def\Element% {9}}\endNode{}\Node% {\def\Element% {10}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}How do you think it would feel to program in a language that has no notion of a loop? This language would have no \Node% {\def\Element% {11}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}for\endSeq{}\endNode{}. No \Node% {\def\Element% {12}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}do\endSeq{}\endNode{}. No \Node% {\def\Element% {13}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}while\endSeq{}\endNode{}. Not even \Node% {\def\Element% {14}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}foreach\endSeq{}\endNode{}. In fact, it doesn't even have a notion of a variable that can be modified.\endPar{}\endNode{}\Node% {\def\Element% {15}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Do you think it would be painful? Maybe primitive? Does it remind you of punched cards in the 1960s?\endPar{}\endNode{}\Node% {\def\Element% {16}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}What do you think it would feel like to program in a language that has no \Node% {\def\Element% {17}}\Seq% {\def\fPosture% {italic}}need\endSeq{}\endNode{} for a loop? No \Node% {\def\Element% {18}}\Seq% {\def\fPosture% {italic}}need\endSeq{}\endNode{} for a \Node% {\def\Element% {19}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}do\endSeq{}\endNode{}, \Node% {\def\Element% {20}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}while\endSeq{}\endNode{}, or a variable that can be modified? A language that has so completely obsoleted these things from programming that adding them to the language would make the language feel primitive?\endPar{}\endNode{}\Node% {\def\Element% {21}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Do you still think it would be primitive? I'm here to tell you that it will make you feel \Node% {\def\Element% {22}}\Seq% {\def\fPosture% {italic}}free\endSeq{}\endNode{}. You'll have more freedom than ever before. Your programs will look completely different. You'll wonder why on earth you ever wrote a loop.\endPar{}\endNode{}\Node% {\def\Element% {23}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}What's the catch?\endPar{}\endNode{}\Node% {\def\Element% {24}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}You have to learn a completely different way of thinking about everything.\endPar{}\endNode{}\Node% {\def\Element% {25}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}OK, that was a little dramatic. You only have a learn a completely different way of thinking about computing.\endPar{}\endNode{}\Node% {\def\Label% {THE.1971.NOVA}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {2}\def\sbNom% {12.96\p@}\def\sbMin% {12.96\p@}\def\sbMax% {12.96\p@}\def\sbConditional% {1}\def\saNom% {8.64\p@}\def\saMin% {8.64\p@}\def\saMax% {8.64\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {27}\def\ProcessingMode% {title-sosofo-mode}}The 1971 Nova\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {27}}\endNode{}\Node% {\def\Element% {28}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}I first learned how to drive a car in high school, like most Americans. My parents owned a rather boring 1986 Pontiac. It was a family car with a family car engine, which means it didn't have a lot of enthusiasm for acceleration.\endPar{}\endNode{}\Node% {\def\Element% {29}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}My parents had bought a car for me to drive about 10 years before I could even drive legally. It was a 1971 Nova. A \Node% {\def\Element% {30}}\Seq% {\def\fPosture% {italic}}big\endSeq{}\endNode{} car. Twice as heavy as the Pontiac and twice as old. It was painted a deep orange -\/-\/ which worked well, since then the rust wasn't as obvious. It had been stored in a barn for 10 years. Mice had eaten away at part of the seats, and it smelled bad inside. My dad got it cheap because it had been in at least one serious wreck already, though it had been mostly repaired.\endPar{}\endNode{}\Node% {\def\Element% {31}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}My dad got the car out and running for me. Like everything else about the car, its engine was big -\/-\/ 350 cubic inches. I remember hating the car at first. Its primitive carbareuter required just the right touch to keep the engine from stalling -\/-\/ much less forgiving than the fuel-\/injected car I was used to.\endPar{}\endNode{}\Node% {\def\Element% {32}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}But before long I discovered something -\/-\/ this car was fast. Despite being old, and in not very good condition, if I pressed the accelerator the wrong (or right?) way, it would take off so quick I'd have to hit the brakes to avoid hitting something.\endPar{}\endNode{}\Node% {\def\Element% {33}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}That car must have been really something when it was new. State of the art, with a massive engine and gleaming paint, and comfortable expansive seats. Yet even in its state, it was so powerful that it could run on less than its full eight cylinders and one might never even notice a problem.\endPar{}\endNode{}\Node% {\def\Element% {34}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}I want to show you just the right touch to using Haskell. The touch that will leave you stunned at how you created something amazing almost before you knew it.\endPar{}\endNode{}\Node% {\def\Element% {35}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}I want you to feel the fun of using a no-\/holds-\/barred language. A language that has no loops because \Node% {\def\Element% {36}}\Seq% {\def\fPosture% {italic}}we don't need them.\endSeq{}\endNode{}\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\endSeq{}\endSpS{}\endNode{}\Node% {\def\Label% {GETTING.ACQUAINTED}}\SpS% {\def\PageNColumns% {1}\def\PageNumberRestart% {0}\def\PageNumberFormat% {1}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\InputWhitespaceTreatment% {collapse}\def\Quadding% {start}\def\fSize% {10\p@}\def\fWeight% {medium}\def\fPosture% {upright}\def\fFamName{Times-New-Roman}\def\LineSpacing% {13\p@}\def\LineSpacingFactor% {0}} \SpSOtherBackLeftFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherBackLeftHeader% {\Seq% {\def\fPosture% {italic}}\Node% {\def\Element% {38}\def\ProcessingMode% {hf-mode}}\Seq% {}Chapter 2. Getting Acquainted\endSeq{}\endNode{}\endSeq{}} \SpSOtherBackCenterFooter% {} \SpSOtherBackCenterHeader% {} \SpSOtherBackRightFooter% {} \SpSOtherBackRightHeader% {} \SpSFirstBackLeftFooter% {} \SpSFirstBackLeftHeader% {} \SpSFirstBackCenterFooter% {} \SpSFirstBackCenterHeader% {} \SpSFirstBackRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstBackRightHeader% {} \SpSOtherFrontLeftFooter% {} \SpSOtherFrontLeftHeader% {} \SpSOtherFrontCenterFooter% {} \SpSOtherFrontCenterHeader% {} \SpSOtherFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherFrontRightHeader% {\Seq% {\def\fPosture% {italic}}\Node% {\def\Element% {38}\def\ProcessingMode% {hf-mode}}\Seq% {}Chapter 2. Getting Acquainted\endSeq{}\endNode{}\endSeq{}} \SpSFirstFrontLeftFooter% {} \SpSFirstFrontLeftHeader% {} \SpSFirstFrontCenterFooter% {} \SpSFirstFrontCenterHeader% {} \SpSFirstFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstFrontRightHeader% {}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fSize% {20.736\p@}\def\LineSpacing% {26.957\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {1}\def\sbNom% {15.552\p@}\def\sbMin% {15.552\p@}\def\sbMax% {15.552\p@}\def\sbConditional% {1}\def\KeepWithNext% {1}}Chapter 2. \Seq% {}\Node% {\def\Element% {38}\def\ProcessingMode% {component-title-mode}}Getting Acquainted\endNode{}\endSeq{}\endPar{}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {italic}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\sbNom% {6.48\p@}\def\sbMin% {6.48\p@}\def\sbMax% {6.48\p@}\def\sbConditional% {1}\def\saNom% {10.368\p@}\def\saMin% {10.368\p@}\def\saMax% {10.368\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Seq% {}\Node% {\def\Element% {39}\def\ProcessingMode% {component-title-mode}}Installing Compilers\endNode{}\endSeq{}\endPar{}\endSeq{}\Node% {\def\Element% {38}}\endNode{}\Node% {\def\Element% {39}}\endNode{}\Node% {\def\Element% {40}}\Seq% {}\endSeq{}\endNode{}\Node% {\def\Element% {43}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}First thing to do is familiarize yourself with the engine of Haskell -\/-\/ the compilers or interpreters that you'll be using.\endPar{}\endNode{}\Node% {\def\Element% {44}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Haskell can be either compiled or interpreted. For an interpreter, you could use Hugs or GHC. For a compiler, you could use GHC or nhc98. GHC provides both an interpreter and compiler.\endPar{}\endNode{}\Node% {\def\Label% {INSTALLING.GHC}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\Node% {\def\Element% {46}}\Seq% {}\endSeq{}\endNode{} I'm going to use GHC in these examples, though you can usually substitute Hugs or nhc98. You can find it in your operating system distribution in many cases. Or you can find it at \Node% {\def\Element% {49}}\Seq% {}http://www.haskell.org/ghc/\endSeq{}\endNode{}.\endPar{}\endNode{}\Node% {\def\Element% {50}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Build it and install it -\/-\/ it's not hard.\endPar{}\endNode{}\Node% {\def\Label% {MISSINGH.INSTALLING}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\Node% {\def\Element% {52}}\Seq% {}\endSeq{}\endNode{} These examples are also going to use my MissingH library. You can download it from \Node% {\def\Element% {55}}\Seq% {}http://quux.org/devel/missingh\endSeq{}\endNode{}. The distribution contains installation instructions, which should be no trouble to follow. You'll need 0.4.2 or above.\endPar{}\endNode{}\Node% {\def\Element% {56}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}That was easy. You don't even have to replace the oil.\endPar{}\endNode{}\endSeq{}\endSpS{}\endNode{}\Node% {\def\Label% {THE.ENGINE}}\SpS% {\def\PageNColumns% {1}\def\PageNumberRestart% {0}\def\PageNumberFormat% {1}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\InputWhitespaceTreatment% {collapse}\def\Quadding% {start}\def\fSize% {10\p@}\def\fWeight% {medium}\def\fPosture% {upright}\def\fFamName{Times-New-Roman}\def\LineSpacing% {13\p@}\def\LineSpacingFactor% {0}} \SpSOtherBackLeftFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherBackLeftHeader% {\Seq% {\def\fPosture% {italic}}\Node% {\def\Element% {58}\def\ProcessingMode% {hf-mode}}\Seq% {}Chapter 3. The Engine\endSeq{}\endNode{}\endSeq{}} \SpSOtherBackCenterFooter% {} \SpSOtherBackCenterHeader% {} \SpSOtherBackRightFooter% {} \SpSOtherBackRightHeader% {} \SpSFirstBackLeftFooter% {} \SpSFirstBackLeftHeader% {} \SpSFirstBackCenterFooter% {} \SpSFirstBackCenterHeader% {} \SpSFirstBackRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstBackRightHeader% {} \SpSOtherFrontLeftFooter% {} \SpSOtherFrontLeftHeader% {} \SpSOtherFrontCenterFooter% {} \SpSOtherFrontCenterHeader% {} \SpSOtherFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherFrontRightHeader% {\Seq% {\def\fPosture% {italic}}\Node% {\def\Element% {58}\def\ProcessingMode% {hf-mode}}\Seq% {}Chapter 3. The Engine\endSeq{}\endNode{}\endSeq{}} \SpSFirstFrontLeftFooter% {} \SpSFirstFrontLeftHeader% {} \SpSFirstFrontCenterFooter% {} \SpSFirstFrontCenterHeader% {} \SpSFirstFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstFrontRightHeader% {}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fSize% {20.736\p@}\def\LineSpacing% {26.957\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {1}\def\sbNom% {15.552\p@}\def\sbMin% {15.552\p@}\def\sbMax% {15.552\p@}\def\sbConditional% {1}\def\KeepWithNext% {1}}Chapter 3. \Seq% {}\Node% {\def\Element% {58}\def\ProcessingMode% {component-title-mode}}The Engine\endNode{}\endSeq{}\endPar{}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {italic}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\sbNom% {6.48\p@}\def\sbMin% {6.48\p@}\def\sbMax% {6.48\p@}\def\sbConditional% {1}\def\saNom% {10.368\p@}\def\saMin% {10.368\p@}\def\saMax% {10.368\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Seq% {}\Node% {\def\Element% {59}\def\ProcessingMode% {component-title-mode}}Using the Compiler and Basic Syntax\endNode{}\endSeq{}\endPar{}\endSeq{}\Node% {\def\Element% {58}}\endNode{}\Node% {\def\Element% {59}}\endNode{}\Node% {\def\Element% {60}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Your new Haskell engine is a little different from ones you've used before. Haskell is a \Node% {\def\Element% {61}}\Seq% {\def\fPosture% {italic}}lazy\endSeq{}\endNode{}, \Node% {\def\Element% {62}}\Seq% {\def\fPosture% {italic}}purely functional\endSeq{}\endNode{} language.\endPar{}\endNode{}\Node% {\def\Label% {NATURE.OF.HASKELL}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {2}\def\sbNom% {12.96\p@}\def\sbMin% {12.96\p@}\def\sbMax% {12.96\p@}\def\sbConditional% {1}\def\saNom% {8.64\p@}\def\saMin% {8.64\p@}\def\saMax% {8.64\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {64}\def\ProcessingMode% {title-sosofo-mode}}The Nature of Haskell\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {64}}\endNode{}\Node% {\def\Label% {NATURE.LAZY}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\Node% {\def\Element% {66}}\Seq% {}\endSeq{}\endNode{} It's \Node% {\def\Element% {68}}\Seq% {\def\fPosture% {italic}}lazy\endSeq{}\endNode{} because it doesn't do any work until it really needs to. That sounds simple, but it's a tremendously powerful concept that is pervasive in the language.\endPar{}\endNode{}\Node% {\def\Element% {69}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\Node% {\def\Element% {70}}\Seq% {}\endSeq{}\endNode{} It's \Node% {\def\Element% {72}}\Seq% {\def\fPosture% {italic}}functional\endSeq{}\endNode{} because Haskell deals a lot with functions. Functions are not just chunks of reusable code. In Haskell, they're also things we pass around as arguments. We create them out of thin air and manipulate them with the same ease we'd manipulate strings in some other languages \Node% {\def\Element% {73}}\Seq% {}\Seq% {\def\fSize% {6\p@}\def\PositionPointShift% {4\p@}\def\PositionPointShiftFactor% {0}}1\endSeq{}\PageFootnote% {}{\Node% {\def\Element% {74}}\Par% {\def\fSize% {9\p@}\def\Quadding% {start}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {16\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-16\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {wrap}\def\fWeight% {medium}\def\fPosture% {upright}\def\fFamName{Times-New-Roman}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\LineField% {\def\FieldWidth% {16\p@}\def\FieldWidthFactor% {0}}1. \endLineField{}OK, we admit that manipulating strings is not that easy in some languages. We're not talking about those languages here.\endPar{}\endNode{}}\endSeq{}\endNode{}. Think about that for a second. In Haskell, you pass and manipulate \Node% {\def\Element% {75}}\Seq% {\def\fPosture% {italic}}code\endSeq{}\endNode{}. Being functional also means that Haskell is not imperative. An imperative language is one where you tell the computer what actions to perform and in what order. Examples of imperative languages include C, C++, Java, Python, Perl, Assembler, BASIC, C\#, Pascal, Fortran, COBOL, etc. You can tell we're onto something odd here when I tell you that Haskell is, in all likelihood, not in the same class of languages as \Node% {\def\Element% {76}}\Seq% {\def\fPosture% {italic}}every language you have ever used\endSeq{}\endNode{} (except perhaps for Make, but that''s not functional either). For the record, some other functional languages include Lisp, Scheme, and OCaml.\endPar{}\endNode{}\Node% {\def\Element% {77}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\Node% {\def\Element% {78}}\Seq% {}\endSeq{}\endNode{} Haskell is \Node% {\def\Element% {81}}\Seq% {\def\fPosture% {italic}}pure functional\endSeq{}\endNode{} because there are no side-\/effects. Every time you call a function with certain paramenters, the function returns the same thing. Every. Single. Time. There are no exceptions\Node% {\def\Element% {82}}\Seq% {}\Seq% {\def\fSize% {6\p@}\def\PositionPointShift% {4\p@}\def\PositionPointShiftFactor% {0}}2\endSeq{}\PageFootnote% {}{\Node% {\def\Element% {83}}\Par% {\def\fSize% {9\p@}\def\Quadding% {start}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {16\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-16\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {wrap}\def\fWeight% {medium}\def\fPosture% {upright}\def\fFamName{Times-New-Roman}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\LineField% {\def\FieldWidth% {16\p@}\def\FieldWidthFactor% {0}}2. \endLineField{}OK, I lied. GHC has some "unsafe" extensions. But they are not for mere mortals to use. They're more there for the people that write compilers. So pay no attention to the man behind the curtain.\endPar{}\endNode{}}\endSeq{}\endNode{}. Oh, functions also do not modify state. They don't change the world. They don't change some global variables or counters. In Haskell, functions don't change things. They just return an altered copy of reality. And this is a good thing, too, because Haskell's reality would be a scary thing indeed if functions could just up and modify it.\endPar{}\endNode{}\Node% {\def\Element% {84}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}You may be wondering how in the world we do I/O in Haskell then. In C, a function like fgets() is bound to return different things even when called with the same input. I/O changes the world. A specific call to fprintf() could cause this printer to start spewing out paper. but Haskell functions don't modify state. They don't change the world. Well, Haskell has a way to deal with I/O, and it involves \Node% {\def\Element% {85}}\Seq% {\def\fPosture% {italic}}actions\endSeq{}\endNode{}. We'll get to that in a bit.\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Label% {TEST.DRIVE}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {2}\def\sbNom% {12.96\p@}\def\sbMin% {12.96\p@}\def\sbMax% {12.96\p@}\def\sbConditional% {1}\def\saNom% {8.64\p@}\def\saMin% {8.64\p@}\def\saMax% {8.64\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {87}\def\ProcessingMode% {title-sosofo-mode}}Test Drive\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {87}}\endNode{}\Node% {\def\Element% {88}}\endNode{}\Node% {\def\Element% {89}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Let's take Haskell for a spin. From here on out, I'm going to show you various Haskell examples using GHC. I'm also going to use Python to illustrate a traditional, imperative approach to the same problems. That's not because I'm trying to say that Python is better than your favorite imperative language. Half the time I'm not even showing you idiomatic Python -\/-\/ I'm illustrating typical iterative algorithms, not showing off Python. I'm just using Python because it should be easily understood by a wide audience, even if your favorite language is Java, C, or Perl.\endPar{}\endNode{}\Node% {\def\Element% {90}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Now then. Let's say we want to write an implementation of the Unix utility \Node% {\def\Element% {91}}\Seq% {\def\fWeight% {bold}}grep\endSeq{}\endNode{}. The \Node% {\def\Element% {92}}\Seq% {\def\fWeight% {bold}}grep\endSeq{}\endNode{} command is used to search for data in files. It will simply display every line containing a particular search term.\endPar{}\endNode{}\Node% {\def\Element% {93}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {94}\def\ProcessingMode% {title-sosofo-mode}}An Imperative grep\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {94}}\endNode{}\Node% {\def\Element% {95}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}We're going to start with a very simple version. Our first grep simply reads from standard input and prints all lines containing the word "Haskell" to standard output. Simple enough.\endPar{}\endNode{}\Node% {\def\Element% {96}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Here's how an imperative programmer might approach it:\endPar{}\endNode{}\Node% {\def\Element% {97}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\#!/usr/bin/python2.3 \# simplegrep.py import sys while True: line = sys.stdin.readline() if line == '': break if line.find("Haskell") != -\/1: sys.stdout.write(line) \endPar{}\endNode{}\Node% {\def\Element% {98}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}That looks fairly normal. We have a \Node% {\def\Element% {99}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}while\endSeq{}\endNode{} loop. Each time through the loop, we read a line from standard input. If it's empty (meaning we reached the end of the file), we \Node% {\def\Element% {100}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}break\endSeq{}\endNode{} out of the while loop, terminating the program.\endPar{}\endNode{}\Node% {\def\Element% {101}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Otherwise, we check to see if the line contains the word Haskell. If it does, we display it. Simple, right?\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {102}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {103}\def\ProcessingMode% {title-sosofo-mode}}A Haskell grep\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {103}}\endNode{}\Node% {\def\Element% {104}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Here's how we could do that in Haskell:\endPar{}\endNode{}\Node% {\def\Element% {105}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}-\/-\/ simplegrep1.hs import MissingH.List main = do c <\/-\/ getContents putStr (unlines(filter (\char92{}line -\/>\/ contains "Haskell" line) (lines c))) \endPar{}\endNode{}\Node% {\def\Element% {106}}\DisplayGroup% {\def\StartIndent% {68\p@}\def\StartIndentFactor% {0}\def\fSize% {9\p@}\def\fWeight% {medium}\def\fPosture% {upright}\def\fFamName{Arial}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Node% {\def\Element% {107}}\Par% {\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\Seq% {\def\fFamName{Arial}\def\fWeight% {bold}}Tip: \endSeq{}An experienced imperative programmer might look at this code, and the discussion below, and conclude that it's terrible because it reads the entire file into memory before processing it. That would be a perfectly valid complaint about a program like this in an imperative language.\endPar{}\endNode{}\Node% {\def\Element% {108}}\Par% {\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}However, Haskell is lazy, so your complaint is not valid with this program. You'll see why later.\endPar{}\endNode{}\endDisplayGroup{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {109}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {110}\def\ProcessingMode% {title-sosofo-mode}}Compiling grep\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {110}}\endNode{}\Node% {\def\Element% {111}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}To compile this, use a command such as:\endPar{}\endNode{}\Node% {\def\Element% {112}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\$ \Node% {\def\Element% {113}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {8.1\p@}\def\fWeight% {bold}}ghc -\/-\/make -\/package MissingH -\/o simplegrep1 simplegrep1.hs\endSeq{}\endNode{} \endPar{}\endNode{}\Node% {\def\Element% {114}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}This runs the Haskell compiler, telling it to make an executable that uses the MissingH package. It will produce an executable named \Node% {\def\Element% {115}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}simplegrep1\endSeq{}\endNode{} based on the source code in \Node% {\def\Element% {116}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}simplegrep1.hs\endSeq{}\endNode{}. You can now experiment with this executable.\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {117}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {118}\def\ProcessingMode% {title-sosofo-mode}}What grep Tells Us About The World\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {118}}\endNode{}\Node% {\def\Element% {119}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Let's look back at the source code for grep. From this example, there are some things to note:\endPar{}\endNode{}\Node% {\def\Element% {120}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\Node% {\def\Element% {121}}\DisplayGroup% {\def\StartIndent% {58\p@}\def\StartIndentFactor% {0}}\Par% {\def\FirstLineStartIndent% {-10\p@}\def\FirstLineStartIndentFactor% {0}\def\fFamName{Times-New-Roman}\def\fWeight% {medium}\def\fSize% {10\p@}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}}\Seq% {}\LineField% {\def\fSize% {8\p@}\def\PositionPointShift% {0\p@}\def\PositionPointShiftFactor% {0}\def\FieldWidth% {10\p@}\def\FieldWidthFactor% {0}}\Character{8226}\endLineField{}\endSeq{}\Node% {\def\Element% {122}\def\ProcessingMode% {listitem-content-mode}}\Seq% {}The main entry point of every Haskell program is an action named \Node% {\def\Element% {123}\def\ProcessingMode% {listitem-content-mode}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}main\endSeq{}\endNode{}.\endSeq{}\endNode{}\endPar{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {124}}\DisplayGroup% {\def\StartIndent% {58\p@}\def\StartIndentFactor% {0}}\Par% {\def\FirstLineStartIndent% {-10\p@}\def\FirstLineStartIndentFactor% {0}\def\fFamName{Times-New-Roman}\def\fWeight% {medium}\def\fSize% {10\p@}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}}\Seq% {}\LineField% {\def\fSize% {8\p@}\def\PositionPointShift% {0\p@}\def\PositionPointShiftFactor% {0}\def\FieldWidth% {10\p@}\def\FieldWidthFactor% {0}}\Character{8226}\endLineField{}\endSeq{}\Node% {\def\Element% {125}\def\ProcessingMode% {listitem-content-mode}}\Seq% {}Here, you can see we have used a \Node% {\def\Element% {126}\def\ProcessingMode% {listitem-content-mode}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}do\endSeq{}\endNode{} block. This is as close as Haskell gets to imperative programming. A \Node% {\def\Element% {127}\def\ProcessingMode% {listitem-content-mode}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}do\endSeq{}\endNode{} block is used to sequence actions, and is usually used with I/O.\endSeq{}\endNode{}\endPar{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {128}}\DisplayGroup% {\def\StartIndent% {58\p@}\def\StartIndentFactor% {0}}\Par% {\def\FirstLineStartIndent% {-10\p@}\def\FirstLineStartIndentFactor% {0}\def\fFamName{Times-New-Roman}\def\fWeight% {medium}\def\fSize% {10\p@}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}}\Seq% {}\LineField% {\def\fSize% {8\p@}\def\PositionPointShift% {0\p@}\def\PositionPointShiftFactor% {0}\def\FieldWidth% {10\p@}\def\FieldWidthFactor% {0}}\Character{8226}\endLineField{}\endSeq{}\Node% {\def\Element% {129}\def\ProcessingMode% {listitem-content-mode}}\Seq% {}In this, and many other, Haskell examples, the amount of indentation you use is syntactically significant. Python programmers will find this concept quite familiar. For those of you that have a contempt for this style, let me say two things: First, this style is optional, and plenty of Haskell programmers don't use it. Second, I'm going to be using this style throughout this tutorial so you can see what it looks like. I encourage you to try it, and decide whether to use it after you've tried it.\endSeq{}\endNode{}\endPar{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {130}}\DisplayGroup% {\def\StartIndent% {58\p@}\def\StartIndentFactor% {0}}\Par% {\def\FirstLineStartIndent% {-10\p@}\def\FirstLineStartIndentFactor% {0}\def\fFamName{Times-New-Roman}\def\fWeight% {medium}\def\fSize% {10\p@}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}}\Seq% {}\LineField% {\def\fSize% {8\p@}\def\PositionPointShift% {0\p@}\def\PositionPointShiftFactor% {0}\def\FieldWidth% {10\p@}\def\FieldWidthFactor% {0}}\Character{8226}\endLineField{}\endSeq{}\Node% {\def\Element% {131}\def\ProcessingMode% {listitem-content-mode}}\Seq% {}Haskell has two types of comments. Two dashes are used to start a comment that extends to the end of a line. You can enclose a multi-\/line comment between \Node% {\def\Element% {132}\def\ProcessingMode% {listitem-content-mode}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}\{-\/\endSeq{}\endNode{} and \Node% {\def\Element% {133}\def\ProcessingMode% {listitem-content-mode}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}-\/\}\endSeq{}\endNode{}.\endSeq{}\endNode{}\endPar{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {134}}\DisplayGroup% {\def\StartIndent% {58\p@}\def\StartIndentFactor% {0}}\Par% {\def\FirstLineStartIndent% {-10\p@}\def\FirstLineStartIndentFactor% {0}\def\fFamName{Times-New-Roman}\def\fWeight% {medium}\def\fSize% {10\p@}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}}\Seq% {}\LineField% {\def\fSize% {8\p@}\def\PositionPointShift% {0\p@}\def\PositionPointShiftFactor% {0}\def\FieldWidth% {10\p@}\def\FieldWidthFactor% {0}}\Character{8226}\endLineField{}\endSeq{}\Node% {\def\Element% {135}\def\ProcessingMode% {listitem-content-mode}}\Seq% {}Function calls don't need parentheses, though sometimes parentheses are necessary to separate elements of a call.\endSeq{}\endNode{}\endPar{}\endDisplayGroup{}\endNode{}\endDisplayGroup{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {136}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {137}\def\ProcessingMode% {title-sosofo-mode}}Analyzing Haskell grep\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {137}}\endNode{}\Node% {\def\Element% {138}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Let's look at this program. Its first line has a comment. The next line is an \Node% {\def\Element% {139}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}import\endSeq{}\endNode{} statement. These statements tell the compiler "make available all the names defined in this module." You can find a reference to these modules at \Node% {\def\Element% {140}}\Seq% {}\Seq% {}\Seq% {}GHC's Hierarchical Libraries page\endSeq{}\Seq% {}\Seq% {\def\fSize% {6\p@}\def\PositionPointShift% {4\p@}\def\PositionPointShiftFactor% {0}}3\endSeq{}\PageFootnote% {}{\Par% {\def\fFamName{Times-New-Roman}\def\fSize% {9\p@}\def\fPosture% {upright}\def\Quadding% {start}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {16\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-16\p@}\def\FirstLineStartIndentFactor% {0}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\LineField% {\def\FieldWidth% {16\p@}\def\FieldWidthFactor% {0}}3. \endLineField{}http://www.haskell.org/ghc/docs/latest/html/libraries/index.html\endPar{}}\endSeq{}\endSeq{}\endSeq{}\endNode{} and at the \Node% {\def\Element% {141}}\Seq% {}\Seq% {}\Seq% {}MissingH reference area\endSeq{}\Seq% {}\Seq% {\def\fSize% {6\p@}\def\PositionPointShift% {4\p@}\def\PositionPointShiftFactor% {0}}4\endSeq{}\PageFootnote% {}{\Par% {\def\fFamName{Times-New-Roman}\def\fSize% {9\p@}\def\fPosture% {upright}\def\Quadding% {start}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {16\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-16\p@}\def\FirstLineStartIndentFactor% {0}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\LineField% {\def\FieldWidth% {16\p@}\def\FieldWidthFactor% {0}}4. \endLineField{}http://gopher.quux.org:70/devel/missingh/html/index.html\endPar{}}\endSeq{}\endSeq{}\endSeq{}\endNode{}. In this case, we are importing \Node% {\def\Element% {142}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}MissingH.List\endSeq{}\endNode{} for the \Node% {\def\Element% {143}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}contains\endSeq{}\endNode{} function. All the other functions we use are available by default. Technically speaking, they're defined in the \Node% {\def\Element% {144}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}Prelude\endSeq{}\endNode{} module, which is always imported by default.\endPar{}\endNode{}\Node% {\def\Element% {145}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}After the \Node% {\def\Element% {146}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}import\endSeq{}\endNode{}, there's the definition of \Node% {\def\Element% {147}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}main\endSeq{}\endNode{}, which consists of a \Node% {\def\Element% {148}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}do\endSeq{}\endNode{} block of two statements. The first statement is \Node% {\def\Element% {149}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}c <\/-\/ getContents\endSeq{}\endNode{}. That says, effectively, "evaluate the \Node% {\def\Element% {150}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}getContents\endSeq{}\endNode{} action and store the result in c". Like I said, we'll go into more detail on actions later. For now you should just know that the only (common) way to "run an action" is to store it in some variable using the \Node% {\def\Element% {151}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}<\/-\/\endSeq{}\endNode{} operator.\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {152}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {153}\def\ProcessingMode% {title-sosofo-mode}}A New, Expanded Haskell grep\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {153}}\endNode{}\Node% {\def\Element% {154}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}The next line is the real fun one. Before I explain it, I'm going to show you a new version of the Haskell grep. This version does exactly the same thing as the first one, but splits things out to make them easier to understand.\endPar{}\endNode{}\Node% {\def\Element% {155}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}-\/-\/ simplegrep2.hs import MissingH.List filterfunc line = contains "Haskell" line main = do c <\/-\/ getContents let inputlines = lines c let outputlines = filter filterfunc inputlines let outputstring = unlines outputlines putStr outputstring \endPar{}\endNode{}\Node% {\def\Element% {156}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Let's look at this new example. It starts with a comment and an \Node% {\def\Element% {157}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}import\endSeq{}\endNode{}, just like before. Next, we have a line defining \Node% {\def\Element% {158}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filterfunc\endSeq{}\endNode{}. \Node% {\def\Element% {159}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filterfunc\endSeq{}\endNode{} is a function that takes one parameter, named \Node% {\def\Element% {160}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}line\endSeq{}\endNode{}. The return value if the function is the one obtained by calling \Node% {\def\Element% {161}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}contains "Haskell" line\endSeq{}\endNode{}. This calls the \Node% {\def\Element% {162}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}contains\endSeq{}\endNode{} function, passing it two parameters. \Node% {\def\Element% {163}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}contains\endSeq{}\endNode{} returns True or False depending on whether or not the word Haskell occurred in the given line.\endPar{}\endNode{}\Node% {\def\Element% {164}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Next, we move on into \Node% {\def\Element% {165}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}main\endSeq{}\endNode{}.\endPar{}\endNode{}\Node% {\def\Element% {166}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}First thing we do is call \Node% {\def\Element% {167}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}getContents\endSeq{}\endNode{}. The \Node% {\def\Element% {168}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}getContents\endSeq{}\endNode{} action returns a string representing all data read from stdin. Some imperative languages have a similar function, which would read the entire contents into memory, then return it. That's bad -\/-\/ if you're grepping through a 5GB file, your system better have 5GB of RAM or things will grind to a halt.\endPar{}\endNode{}\Node% {\def\Element% {169}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Because Haskell is lazy, it doesn't have this problem. It only asks for data from standard input when the program needs it, and it releases the memory as soon as it knows the program will never need the data again. Clever, eh?\endPar{}\endNode{}\Node% {\def\Element% {170}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Next, we call \Node% {\def\Element% {171}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}lines c\endSeq{}\endNode{}. The \Node% {\def\Element% {172}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}lines\endSeq{}\endNode{} function takes a string parameter and returns a list of strings. It simply splits up the input string by newline boundaries, so the resulting list is a list of lines. Remember, Haskell is lazy, so we're not really storing a massive list of all lines of the file in memory -\/-\/ they're just consumed as needed. The \Node% {\def\Element% {173}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}let inputlines =\endSeq{}\endNode{} part of the statement assigns the result of this call to the variable named \Node% {\def\Element% {174}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}inputlines\endSeq{}\endNode{}.\endPar{}\endNode{}\Node% {\def\Element% {175}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Next, we call \Node% {\def\Element% {176}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filter filterfunc inputlines\endSeq{}\endNode{}. This is a cool function. All your friends will be impressed by \Node% {\def\Element% {177}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filter\endSeq{}\endNode{}. Well, maybe they'll be jealous of it.\endPar{}\endNode{}\Node% {\def\Element% {178}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\Node% {\def\Element% {179}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filter\endSeq{}\endNode{} is our first opportunity to really see the functional nature of Haskell at work. It takes two parameters. The first parameter is actually a function! This function is supposed to take an item and return True or False. The second parameter is a list. It also returns a list. \Node% {\def\Element% {180}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filter\endSeq{}\endNode{} will call the supplied function for each item in the list. If the function returns True, the item is in the returned list. If it returns False, the item isn't. In this case, we pass along our \Node% {\def\Element% {181}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filterfunc\endSeq{}\endNode{}, which will filter out the lines that don't contain Haskell.\endPar{}\endNode{}\Node% {\def\Element% {182}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Next, we come to \Node% {\def\Element% {183}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}unlines\endSeq{}\endNode{}. Can you guess that it does the opposite of \Node% {\def\Element% {184}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}lines\endSeq{}\endNode{}? In fact, \Node% {\def\Element% {185}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}unlines\endSeq{}\endNode{} simply takes a list of strings, taken to represent a line, and returns one big string with all those lines separated by the newline character.\endPar{}\endNode{}\Node% {\def\Element% {186}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}The imperative programmer in you probably wants to yell at me about this again -\/-\/ what an inefficient waste of memory! But the Haskell programmer in you should remember that Haskell is lazy. The function works incrementally, building thigns as it goes, and never has to store the whole thing in memory.\endPar{}\endNode{}\Node% {\def\Element% {187}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Finally, we come to \Node% {\def\Element% {188}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}putStr outputstring\endSeq{}\endNode{}. The \Node% {\def\Element% {189}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}putStr\endSeq{}\endNode{} function simply writes a string to standard output. Since it's lazy, it can be thought of as the "driver" for the while process. It demands data from \Node% {\def\Element% {190}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}unlines\endSeq{}\endNode{}, which demands data from \Node% {\def\Element% {191}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filter\endSeq{}\endNode{}, which demands it from \Node% {\def\Element% {192}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}lines\endSeq{}\endNode{}, which demands it from \Node% {\def\Element% {193}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}getContents\endSeq{}\endNode{}. Get this -\/-\/ if we didn't have \Node% {\def\Element% {194}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}putStr\endSeq{}\endNode{} there, the program would never read any data at all, because nothing in the program would require it to be read! That's laziness for you. Isn't it great to be a slacker?\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {195}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {196}\def\ProcessingMode% {title-sosofo-mode}}Haskell grep Broken Down\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {196}}\endNode{}\Node% {\def\Element% {197}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Above, I expanded the grep example. Recall that I earlier mentioned that \Node% {\def\Element% {198}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}do\endSeq{}\endNode{} is the only real imperative-\/like feature in Haskell. That's true. But it seems like we're doing an awful lot of work in imperative mode here, doesn't it? Well, actually only two lines are doing work in "imperative mode": the first and last lines in the \Node% {\def\Element% {199}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}do\endSeq{}\endNode{} block. Let me show you another example to illustrate this:\endPar{}\endNode{}\Node% {\def\Element% {200}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}-\/-\/ simplegrep3.hs import MissingH.List filterfunc line = contains "Haskell" line processfunc1 inputdata = let inputlines = lines inputdata outputlines = filter filterfunc inputlines in unlines outputlines processfunc2 inputdata = unlines(filter (\char92{}line -\/>\/ contains "Haskell" line) (lines inputdata)) processfunc3 inputdata = unlines . filter filterfunc . lines \$ inputdata main = do c <\/-\/ getContents putStr (processfunc3 c) \endPar{}\endNode{}\Node% {\def\Element% {201}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Here, I provided three pure, non-\/imperative \Node% {\def\Element% {202}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}processfunc\endSeq{}\endNode{}s. They all take a String parameter and return a String result. They all are non-\/imperative -\/-\/ they are an expression, not a list of commands.\endPar{}\endNode{}\Node% {\def\Element% {203}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Some people have trouble understanding the difference. Consider the mathematical equation \Node% {\def\Element% {204}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}3 * 4 + 5\endSeq{}\endNode{}. This is an expression. Yet to evaluate this expression, we know that we should first multiply 3 and 4, then add 5 -\/-\/ not add 4 and 5, then multiply by three. There are rules to evaluating an expression.\endPar{}\endNode{}\Node% {\def\Element% {205}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}The same is true in Haskell, but the concept expands. In \Node% {\def\Element% {206}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}processfunc1\endSeq{}\endNode{}, we have only one expression making up the body of the function: \Node% {\def\Element% {207}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}unlines outputlines\endSeq{}\endNode{}. But to evaluate it, Haskell must evaluate \Node% {\def\Element% {208}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}outputlines\endSeq{}\endNode{}. And to do that, it must evaluate \Node% {\def\Element% {209}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}inputlines\endSeq{}\endNode{}. Even though we give it only definitions and an expression, we still get things done right. By the way, every function in Haskell has only one expression. You will never see a Haskell function (aside from actions -\/-\/ a whole different story) that has more than one expression.\endPar{}\endNode{}\Node% {\def\Element% {210}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}The \Node% {\def\Element% {211}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}processfunc2\endSeq{}\endNode{} function does the exact same job as \Node% {\def\Element% {212}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}processfunc1\endSeq{}\endNode{}, it just does it without using any names for things. That's how our first Haskell grep worked. Hopefully, this can help illustrate how this is just an expression evaluation. In Haskell, saying \Node% {\def\Element% {213}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}let inputlines = lines inputdata\endSeq{}\endNode{} doesn't evaluate \Node% {\def\Element% {214}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}lines inputdata\endSeq{}\endNode{} and store the result in \Node% {\def\Element% {215}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}inputlines\endSeq{}\endNode{}. It says, "Hey, Haskell -\/-\/ if you ever need to figure out what \Node% {\def\Element% {216}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}inputlines\endSeq{}\endNode{} means, here's how."\endPar{}\endNode{}\Node% {\def\Element% {217}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Notice also in \Node% {\def\Element% {218}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}processfunc2\endSeq{}\endNode{} the little backslash line arrow thingy. That's an \Node% {\def\Element% {219}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}anonymous function definition\endSeq{}\endNode{}. An anonymous function is a function that has no name. (Clever, eh?) We use them a lot with things like \Node% {\def\Element% {220}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filter\endSeq{}\endNode{}. This anonymous function is the same function as \Node% {\def\Element% {221}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filterfunc\endSeq{}\endNode{} above, just defined differently.\endPar{}\endNode{}\Node% {\def\Element% {222}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Then, \Node% {\def\Element% {223}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}processfunc3\endSeq{}\endNode{} shows you a little bit of what we will cover in (FIXME: ADD LINK TO CHAPTER). You'll see over there how we can write this entire program with less than one line of Haskell code. (Well, one line plus an import, geez, you're so picky!) We do so by doing what I like to call "adding functions". It's pretty slick. Yeah, we take functions and add them up as if they were numbers. (Unix geeks might liken this to pipes.)\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {224}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {2}\def\sbNom% {12.96\p@}\def\sbMin% {12.96\p@}\def\sbMax% {12.96\p@}\def\sbConditional% {1}\def\saNom% {8.64\p@}\def\saMin% {8.64\p@}\def\saMax% {8.64\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {225}\def\ProcessingMode% {title-sosofo-mode}}Test Drive Results\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {225}}\endNode{}\Node% {\def\Element% {226}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}I hope you enjoyed your little Haskell test drive. I've shown you a lot quickly. Don't worry if you don't fully understand everything yet. We'll be using the grep example more soon. And, by the way, you haven't even seen the really cool, mind-\/blowing stuff yet.\endPar{}\endNode{}\Node% {\def\Element% {227}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}But you should have a little taste of what I mean when I say that Haskell is a really different way to look at computing. Did you notice that this entire program doesn't have even one loop? It doesn't even have a reference to \Node% {\def\Element% {228}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}if\endSeq{}\endNode{}! (Yes, Haskell does have \Node% {\def\Element% {229}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}if..then..else\endSeq{}\endNode{}, but us Haskell types don't use it all that often because, well, we don't need to all that often.)\endPar{}\endNode{}\Node% {\def\Element% {230}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Next, you're going to see Haskell's slick, strong, static typing system. I haven't even shown it to you yet, though it's already working (and even caught a bug in my code as I was writing this chapter). It's as strong as Java's, as unintrusive as Perl's or Python's, and as powerful as -\/-\/ well, there's no comparison. It's more powerful than anything you've seen.\endPar{}\endNode{}\Node% {\def\Element% {231}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}After that, we're going to talk about functions. They do a lot in Haskell, and they are \Node% {\def\Element% {232}}\Seq% {\def\fPosture% {italic}}everywhere\endSeq{}\endNode{}. Haskell programmers do very little without thinking of functions somewhere.\endPar{}\endNode{}\Node% {\def\Element% {233}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Hopefully, if that didn't get you excited, you'll at least read on to be able to prove to me, and all your imperative friends, just how wrong you think I am :-\/) (Yes, I do still have some imperative friends. They're nowhere near as lazy as I am.)\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\endSeq{}\endSpS{}\endNode{}\Node% {\def\Label% {SAFETY}}\SpS% {\def\PageNColumns% {1}\def\PageNumberRestart% {0}\def\PageNumberFormat% {1}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\InputWhitespaceTreatment% {collapse}\def\Quadding% {start}\def\fSize% {10\p@}\def\fWeight% {medium}\def\fPosture% {upright}\def\fFamName{Times-New-Roman}\def\LineSpacing% {13\p@}\def\LineSpacingFactor% {0}} \SpSOtherBackLeftFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherBackLeftHeader% {\Seq% {\def\fPosture% {italic}}\Node% {\def\Element% {235}\def\ProcessingMode% {hf-mode}}\Seq% {}Chapter 4. Safety Belts: The Type System\endSeq{}\endNode{}\endSeq{}} \SpSOtherBackCenterFooter% {} \SpSOtherBackCenterHeader% {} \SpSOtherBackRightFooter% {} \SpSOtherBackRightHeader% {} \SpSFirstBackLeftFooter% {} \SpSFirstBackLeftHeader% {} \SpSFirstBackCenterFooter% {} \SpSFirstBackCenterHeader% {} \SpSFirstBackRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstBackRightHeader% {} \SpSOtherFrontLeftFooter% {} \SpSOtherFrontLeftHeader% {} \SpSOtherFrontCenterFooter% {} \SpSOtherFrontCenterHeader% {} \SpSOtherFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSOtherFrontRightHeader% {\Seq% {\def\fPosture% {italic}}\Node% {\def\Element% {235}\def\ProcessingMode% {hf-mode}}\Seq% {}Chapter 4. Safety Belts: The Type System\endSeq{}\endNode{}\endSeq{}} \SpSFirstFrontLeftFooter% {} \SpSFirstFrontLeftHeader% {} \SpSFirstFrontCenterFooter% {} \SpSFirstFrontCenterHeader% {} \SpSFirstFrontRightFooter% {\Seq% {\def\fPosture% {italic}}\insertPageNumber% {}\endSeq{}} \SpSFirstFrontRightHeader% {}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fSize% {20.736\p@}\def\LineSpacing% {26.957\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {1}\def\sbNom% {15.552\p@}\def\sbMin% {15.552\p@}\def\sbMax% {15.552\p@}\def\sbConditional% {1}\def\KeepWithNext% {1}}Chapter 4. \Seq% {}\Node% {\def\Element% {235}\def\ProcessingMode% {component-title-mode}}Safety Belts: The Type System\endNode{}\endSeq{}\endPar{}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {italic}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\sbNom% {6.48\p@}\def\sbMin% {6.48\p@}\def\sbMax% {6.48\p@}\def\sbConditional% {1}\def\saNom% {10.368\p@}\def\saMin% {10.368\p@}\def\saMax% {10.368\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Seq% {}\endSeq{}\endPar{}\endSeq{}\Node% {\def\Element% {235}}\endNode{}\Node% {\def\Element% {236}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Every modern language you use -\/-\/ except, perhaps, for assembler -\/-\/ has a typing system. A typing system is used to identify what sort of data a particular variable holds. You're probably familiar with these typing systems -\/-\/ types such as ints, floats, strings, lists, etc. are common in languages. A typing system acts as your seat belt. It helps prevent mistakes such as 53 + "asdf". There's no real way to add an integer to a string like that, and a typing system helps make sure you don't generate odd results for trying.\endPar{}\endNode{}\Node% {\def\Element% {237}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}In this chapter, you'll learn about both Haskell's type checking and its various data types.\endPar{}\endNode{}\Node% {\def\Element% {238}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {2}\def\sbNom% {12.96\p@}\def\sbMin% {12.96\p@}\def\sbMax% {12.96\p@}\def\sbConditional% {1}\def\saNom% {8.64\p@}\def\saMin% {8.64\p@}\def\saMax% {8.64\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {239}\def\ProcessingMode% {title-sosofo-mode}}A Brief Typing Backgrounder\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {239}}\endNode{}\Node% {\def\Element% {240}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Now, this is a very practical, hands-\/on tutorial, but I've got to go into theory for just a moment to help you understand how Haskell is different from the languages you know if. It won't be painful, I promise.\endPar{}\endNode{}\Node% {\def\Element% {241}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}When we talk about typing systems, we generally talk about two different distinctions in typing systems: strong vs. weak, and static vs. dynamic.\endPar{}\endNode{}\Node% {\def\Element% {242}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {243}\def\ProcessingMode% {title-sosofo-mode}}Strong vs. Weak Typing\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {243}}\endNode{}\Node% {\def\Element% {244}}\Seq% {}\endSeq{}\endNode{}\Node% {\def\Element% {246}}\Seq% {}\endSeq{}\endNode{}\Node% {\def\Element% {248}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Strongly-\/typed languages tend to keep track of types tightly. It knows that this thing over here is an int, that thing over there is a string, and you can't just add them together without converting one to the other. One almost universal characteristic of strongly-\/typed languages is that you must declare the type of every variable you use and the expected types for every function parameter and return value. Examples of strongly-\/typed languages include Python, C, and Java.\endPar{}\endNode{}\Node% {\def\Element% {249}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Weakly-\/typed languages may have an internal notion of types, but they let you trample all over them if you want. You may be able to add the string "5" to the integer 12, but whether you get the string "512" of the integer 17 out of it is going to be language-\/dependant. Some weakly-\/typed languages go so far as to not generate an error if you use a variable you've never set before. Examples of weakly-\/typed languages include Perl and PHP.\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {250}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {251}\def\ProcessingMode% {title-sosofo-mode}}Static vs. Dynamic Checking\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {251}}\endNode{}\Node% {\def\Element% {252}}\Seq% {}\endSeq{}\endNode{}\Node% {\def\Element% {254}}\Seq% {}\endSeq{}\endNode{}\Node% {\def\Element% {256}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Statically-\/typed language perform type checking at compile time. That is, with few or no exceptions, every possible type error is caught before you ever even try to run the program. The exceptions to this rule generally occur with casting, where it's possible to do some really weird things. Examples of statically-\/typed languages include C and Java.\endPar{}\endNode{}\Node% {\def\Element% {257}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Dynamically-\/typed language perform type checking while the program is running. You could be perfectly safe passing an int to a function expecting a string, as long as that function never tries to use it. This lets you get away with things, but at the same time the program can blow up unexpectedly if there's a typing problem in a little-\/used part of code. Examples of dynamically-\/typed languages include Python and Perl.\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {258}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {2}\def\sbNom% {12.96\p@}\def\sbMin% {12.96\p@}\def\sbMax% {12.96\p@}\def\sbConditional% {1}\def\saNom% {8.64\p@}\def\saMin% {8.64\p@}\def\saMax% {8.64\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {259}\def\ProcessingMode% {title-sosofo-mode}}Overview of Haskell's Type System\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {259}}\endNode{}\Node% {\def\Element% {260}}\Seq% {}\endSeq{}\endNode{}\Node% {\def\Element% {262}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Haskell is a strong, statically-\/typed language with type inferencem, polymorphism, and classing.\endPar{}\endNode{}\Node% {\def\Element% {263}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}You understand some of that already, but there are some new terms here. We'll learn about them shortly.\endPar{}\endNode{}\Node% {\def\Element% {264}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Because Haskell is statically-\/typed, type errors are caught at compile time, before you ever run your program. Because it's strongly-\/typed, you don't ever have to worry about type errors at runtime.\endPar{}\endNode{}\Node% {\def\Element% {265}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {14.4\p@}\def\LineSpacing% {18.72\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {3}\def\sbNom% {10.8\p@}\def\sbMin% {10.8\p@}\def\sbMax% {10.8\p@}\def\sbConditional% {1}\def\saNom% {7.2\p@}\def\saMin% {7.2\p@}\def\saMax% {7.2\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {266}\def\ProcessingMode% {title-sosofo-mode}}Type Inference\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {266}}\endNode{}\Node% {\def\Element% {267}}\Seq% {}\endSeq{}\endNode{}\Node% {\def\Element% {269}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}But remember how I said that almost all strongly-\/typed languages force you to declare the types of your variables? Recall from the examples in \Node% {\def\Element% {270}}\Link% {\def\Label% {THE.ENGINE}}\Seq% {}Chapter \Seq% {}3\endSeq{}\endSeq{}\endLink{}\endNode{} that you never actually declared any types. Not only that, but you never even saw types anywhere. How can that be?\endPar{}\endNode{}\Node% {\def\Element% {271}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}The answer is type inference. Let's look at one of those examples again:\endPar{}\endNode{}\Node% {\def\Element% {272}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}-\/-\/ simplegrep2.hs import MissingH.List filterfunc line = contains "Haskell" line main = do c <\/-\/ getContents let inputlines = lines c let outputlines = filter filterfunc inputlines let outputstring = unlines outputlines putStr outputstring \endPar{}\endNode{}\Node% {\def\Element% {273}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Haskell works backwards and forwards to figure out what types things must be. First, Haskell knows that \Node% {\def\Element% {274}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}filterfunc\endSeq{}\endNode{} takes a \Node% {\def\Element% {275}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}String\endSeq{}\endNode{} and returns a \Node% {\def\Element% {276}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}Bool\endSeq{}\endNode{} because of the type of arguments and return value of the \Node% {\def\Element% {277}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}contains\endSeq{}\endNode{} function.\endPar{}\endNode{}\Node% {\def\Element% {278}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Then, in \Node% {\def\Element% {279}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}main\endSeq{}\endNode{}, it knows that \Node% {\def\Element% {280}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}c\endSeq{}\endNode{} is a \Node% {\def\Element% {281}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}String\endSeq{}\endNode{} because that's what \Node% {\def\Element% {282}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}getContents\endSeq{}\endNode{} returns. It similarly knows that \Node% {\def\Element% {283}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}inputlines\endSeq{}\endNode{} is a list of \Node% {\def\Element% {284}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}String\endSeq{}\endNode{}s because that's what \Node% {\def\Element% {285}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}lines\endSeq{}\endNode{} returns. It can track these types all the way down. If you made a mistake somewhere -\/-\/ say, you wrote \Node% {\def\Element% {286}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}unlines c\endSeq{}\endNode{} instead of \Node% {\def\Element% {287}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}unlines outputlines\endSeq{}\endNode{}, the compiler would have noticed the type error and aborted. We'll see a lot more on this later.\endPar{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\endSeq{}\endDisplayGroup{}\endNode{}\Node% {\def\Element% {288}}\DisplayGroup% {\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}\Seq% {}\Seq% {}\Par% {\def\fFamName{Arial}\def\fWeight% {bold}\def\fPosture% {upright}\def\fSize% {17.28\p@}\def\LineSpacing% {22.464\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {0\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\HeadingLevel% {2}\def\sbNom% {12.96\p@}\def\sbMin% {12.96\p@}\def\sbMax% {12.96\p@}\def\sbConditional% {1}\def\saNom% {8.64\p@}\def\saMin% {8.64\p@}\def\saMax% {8.64\p@}\def\saConditional% {1}\def\KeepWithNext% {1}}\Node% {\def\Element% {289}\def\ProcessingMode% {title-sosofo-mode}}Some Quick Experiments with ghci\endNode{}\endPar{}\endSeq{}\Node% {\def\Element% {289}}\endNode{}\Node% {\def\Element% {290}}\Seq% {}\endSeq{}\endNode{}\Node% {\def\Element% {292}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}I'm going to start by introducing a new program to you. It's called \Node% {\def\Element% {293}}\Seq% {\def\fWeight% {bold}}ghci\endSeq{}\endNode{} and is installed by default with the GHC distribution. \Node% {\def\Element% {294}}\Seq% {\def\fWeight% {bold}}ghci\endSeq{}\endNode{} is the GHC interpreter, and lets you easily experiment with Haskell code. If your system doesn't have \Node% {\def\Element% {295}}\Seq% {\def\fWeight% {bold}}ghci\endSeq{}\endNode{}, you can also try \Node% {\def\Element% {296}}\Seq% {}\Seq% {}\Seq% {}hugs\endSeq{}\Seq% {}\Seq% {\def\fSize% {6\p@}\def\PositionPointShift% {4\p@}\def\PositionPointShiftFactor% {0}}1\endSeq{}\PageFootnote% {}{\Par% {\def\fFamName{Times-New-Roman}\def\fSize% {9\p@}\def\fPosture% {upright}\def\Quadding% {start}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {16\p@}\def\StartIndentFactor% {0}\def\FirstLineStartIndent% {-16\p@}\def\FirstLineStartIndentFactor% {0}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}\LineField% {\def\FieldWidth% {16\p@}\def\FieldWidthFactor% {0}}1. \endLineField{}http://www.haskell.org/hugs\endPar{}}\endSeq{}\endSeq{}\endSeq{}\endNode{}, which has many of the same commands. You should be able to just type \Node% {\def\Element% {297}}\Seq% {\def\fWeight% {bold}}ghci\endSeq{}\endNode{} to start up the interpreter.\endPar{}\endNode{}\Node% {\def\Element% {298}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Let's experiment a bit with \Node% {\def\Element% {299}}\Seq% {\def\fWeight% {bold}}ghci\endSeq{}\endNode{}. Try typing in these examples. You should get similar results as me:\endPar{}\endNode{}\Node% {\def\Element% {300}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}Prelude\Entity{gt} \Node% {\def\Element% {301}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {8.1\p@}\def\fWeight% {bold}}5 + 3\endSeq{}\endNode{} 8 \endPar{}\endNode{}\Node% {\def\Element% {302}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Yep, Haskell can do simple math.\endPar{}\endNode{}\Node% {\def\Element% {303}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}Prelude\Entity{gt} \Node% {\def\Element% {304}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {8.1\p@}\def\fWeight% {bold}}"asdf"\endSeq{}\endNode{} "asdf" \endPar{}\endNode{}\Node% {\def\Element% {305}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}We put strings in double quotes.\endPar{}\endNode{}\Node% {\def\Element% {306}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}Prelude\Entity{gt} \Node% {\def\Element% {307}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {8.1\p@}\def\fWeight% {bold}}"Haskell" ++ "is" ++ "cool"\endSeq{}\endNode{} "Haskelliscool" Prelude\Entity{gt} \Node% {\def\Element% {308}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {8.1\p@}\def\fWeight% {bold}}['H', 'a', 's', 'k', 'e', 'l', 'l']\endSeq{}\endNode{} "Haskell" \endPar{}\endNode{}\Node% {\def\Element% {309}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\p@}\def\sbConditional% {1}\def\saNom% {5\p@}\def\saMin% {5\p@}\def\saMax% {5\p@}\def\saConditional% {1}}Strings in Haskell are just lists of characters. \Node% {\def\Element% {310}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {9\p@}}++\endSeq{}\endNode{} is the list concatenation (combining) operator, and since strings are lists, it's also the strong concatenation operator.\endPar{}\endNode{}\Node% {\def\Element% {311}}\Par% {\def\fSize% {9\p@}\def\LineSpacing% {11.7\p@}\def\LineSpacingFactor% {0}\def\StartIndent% {48\p@}\def\StartIndentFactor% {0}\def\fFamName{Courier-New}\def\fWeight% {medium}\def\fPosture% {upright}\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Lines% {asis}\def\InputWhitespaceTreatment% {preserve}\def\sbNom% {10\p@}\def\sbMin% {10\p@}\def\sbMax% {10\p@}\def\sbConditional% {1}\def\saNom% {10\p@}\def\saMin% {10\p@}\def\saMax% {10\p@}\def\saConditional% {1}}Prelude\Entity{gt} \Node% {\def\Element% {312}}\Seq% {\def\fFamName{Courier-New}\def\fSize% {8.1\p@}\def\fWeight% {bold}}[1, 2, 3, 4, 5]\endSeq{}\endNode{} [1,2,3,4,5] \endPar{}\endNode{}\Node% {\def\Element% {313}}\Par% {\def\FirstLineStartIndent% {0\p@}\def\FirstLineStartIndentFactor% {0}\def\Quadding% {start}\def\Hyphenate% {0}\def\Language% {EN}\def\sbNom% {5\p@}\def\sbMin% {5\p@}\def\sbMax% {5\