The "Hello, World!" Functional Program
Haskell, Iteration 1
There are three aspects of Haskell that make it particularly interesting:
- There are no side-effects. Everything is expressed in terms of functions. This makes it a pure functional programming language.
- Haskell uses lazy evaluation to evaluate only the computations that are necessary.
- Haskell is strongly typed at compile type using type inference.
However, we won't look at any of these things this week. This week is to get a Haskell environment working for you.
Not Really Printing "Hello, World"
Your first Haskell program is going to be a program that computes factorials.
In your cs214/haskell
folder, create a folder named
factorial
. In this folder, create these files:
Factorial.hs
, FactorialTest.hs
,
FactorialMain.hs
, and Rakefile
.
Unit Tests
Let's start with the unit tests.
FactorialTest.hs
module Main where import Test.HUnit import System import Factorial {- This is a TestList of TestCases. Each TestCase should make one assertion. You can define as many of these variables as you like. -} factorialTests = TestList [ TestCase (assertEqual "0! should be 1" 1 (factorial 0)), TestCase (assertEqual "1! should be 1" 1 (factorial 1)), TestCase (assertEqual "3! should be 6" 6 (factorial 3)) ] {- Just accept this next bit of code -} checkTests counts = case counts of Counts _ _ errors failures -> if (errors + failures > 0) then exitFailure else (exitWith ExitSuccess) {- This is the main function which will be executed when the executable is invoked on the command line. -} main = runTestTT (TestList [ TestLabel "testing factorial" factorialTests {- If you define more test variables, add TestLabels here -} ]) >>= checkTests
Put this code into FactorialTest.hs
.
Computation
Factorial.hs
module Factorial where factorial 0 = 1 factorial n = n * factorial(n-1)
Put this code in Factorial.hs
.
Managing the Compilation
A rakefile is actually a Ruby program using the rake gem. It can be used to compile any language though:
Rakefile
task :default => :compile task :compile do system "ghc --make FactorialTest.hs" end
Enter this code into Rakefile
.
Running the Tests
You can now compile and run the tests!
Compile everything with the rake
command. Then run
FactorialTest
.
Add to the Tests
Add some more TestCase
s to
FactorialTest.hs
. Test 6!, 13!, and 100!.
A couple things to observe:
- Scientific calculators can't compute 70!.
- Just how fast is Haskell?!
Try Interactive Haskell
Start ghci
at a command line in your
factorial
folder. Enter these commands:
> :load Factorial > factorial 100
Compute some other factorials.
Main Function
FactorialMain.hs
module Main where import Data.String import System.Environment import System.Exit import Factorial {- main program function. Applies "factorial" to all arguments. -} main = getArgs >>= putAnswers . (map factorial) . parse {- gets the command-line arguments -} parse args = map read args {- print results -} putAnswers l = putStr (unlines (map show l))
Be sure to mention to your other computer-science profs how fast Haskell can compute very large factorials.
Put this code into FactorialMain.hs
. Add code to
Rakefile
to compile this program as well. Then run
FactorialMain
like so:
% FactorialMain 100