Haskell on Haswell
How does Haskell run on the new MacBook Air with the Haswell chip? In short, just fine. The mid-2013 MBA represents a practical tradeoff of a little CPU power for a lot of battery life; for Haskellers on the go, the Mac is a solid choice for software development.
Newbies can install Haskell on Mac with ease, using the prebuilt Haskell Platform installer, a typical Mac
PKG compressed in a
DMG virtual disk. Don’t forget to eject the disk, you silly goose.
Expert Haskellers may want to compile Haskell directly from source, with
brew install haskell-platform. On newer Macs, this formula requires a minor tweak to gcc/clang in order to install, but the resulting Haskell Platform it creates in
/usr/local/Cellar/haskell-platform/ is fully operational.
Haskell 7 was tested on a 13” mid-2013 MacBook Pro, with the 1.7GHz i7 version of the processor, and full upgrades to RAM and SDD.
$ specs haskell os ram hd cpu hardware Specs: specs 0.4 https://github.com/mcandre/specs#readme cabal --version cabal-install version 126.96.36.199 using version 1.16.0 of the Cabal library ghc --version The Glorious Glasgow Haskell Compilation System, version 7.6.3 ghc-pkg field haskell-platform version version: 2013.2.0.0 system_profiler SPSoftwareDataType | grep 'System Version' System Version: OS X 10.8.4 (12E3200) system_profiler | grep 'Memory:' Memory: 8 GB Memory: Secure Virtual Memory: Enabled df -h Filesystem Size Used Avail Capacity iused ifree %iused Mounted on /dev/disk0s2 465Gi 56Gi 409Gi 12% 14634549 107293680 12% / devfs 188Ki 188Ki 0Bi 100% 650 0 100% /dev map -hosts 0Bi 0Bi 0Bi 100% 0 0 100% /net map auto_home 0Bi 0Bi 0Bi 100% 0 0 100% /home system_profiler | grep Cores: Total Number of Cores: 2 system_profiler | grep Processors: Number of Processors: 1 system_profiler | grep 'Model Identifier' Model Identifier: MacBookAir6,2
For our first test, Hello World would be just too easy. Instead, we’ll compile a genetic algorithm to sift through the space of random strings until we eventually reach Hello World by testing each random sample for fitness to each of the characters in
$ git clone https://github.com/mcandre/genetics $ cd genetics/ $ cabal install -p random-fu random-source $ make profile ghc --make -O2 -threaded -rtsopts hellogenetics.hs -package base -package random-fu -package random-source -prof -auto-all -caf-all -o hellogenetics-profile [1 of 2] Compiling Genetics ( Genetics.hs, Genetics.o ) [2 of 2] Compiling Main ( hellogenetics.hs, hellogenetics.o ) Linking hellogenetics-profile ... time ./hellogenetics-profile +RTS -N1 -p -hc Hello World! 27.79 real 26.47 user 1.17 sys
That’s <30 seconds from primordial soup to modern homo worldus. If the number of generations in
hellogenetics.hs is lowered to
2 ^ 10, the program completes much faster, (0.41 real time), but the outputs tend to look like
HZllo)Wo-kd!, hardly the civilized Hello World as we know him.
Moving on to the second program, we download an interpreted Cisco IOS7 password decryptor.
$ git clone https://github.com/mcandre/mcandre $ cd mcandre/haskell/ $ ./ios7crypt.hs -h ios7crypt.hs -e <password> --encrypt=<password> Encrypt a password -d <hash> --decrypt=<hash> Decrypt a hash -t --test Unit test IOS7Crypt -h --help Display usage information $ ./ios7crypt.hs -e monkey 04560408042455 $ ./ios7crypt.hs -d 04560408042455 monkey $ time ./ios7crypt.hs -t +++ OK, passed 100 tests. real 0m0.604s user 0m0.530s sys 0m0.066s
That makes for 100 passwords decrypted in slightly over half a second (0.604), not terrible, but not great.
Pro tip for Windows users: When running the same benchmark, either substitute
runhaskell ios7crypt.hs for compatibility with
cmd; or run
./ios7crypt.hs inside of git bash.
If someone wanted to break a bunch of router hashes in Haskell, he’d best rewrite the program in Cloud Haskell, farmed out to a thousand MacBook Airs.
On that note, we benchmark a parallel processing program for solving Project Euler 14, finding the longest Hailstone sequence under 1,000,000 elements.
$ git clone https://github.com/mcandre/projecteuler $ tail problem14.hs longestChainIn = foldl maxLength  . parMap rseq hailstone longestChainUnder :: Integer -> Integer longestChainUnder n = head $ (evens :: [Integer]) `par` (odds :: [Integer]) `pseq` maxLength evens odds where evens = longestChainIn [0, 2 .. n] odds = longestChainIn [1, 3 .. n] main :: IO () main = (print . longestChainUnder) 1000000 $ time ./problem14.hs -RTS -N 837799 real 3m26.333s user 3m17.689s sys 0m5.247s
The compiled version runs a bit faster, but it’s still not much fun to watch. Maybe a good time to heat up a slice of pizza.
$ ghc --make problem14.hs -with-rtsopts='-K5000M -RTS -N' -threaded -rtsopts -prof $ time ./problem14 -RTS -N 837799 real 1m17.886s user 1m0.447s sys 0m9.234s
All in all, Haskell on Haswell is responsive and easy to use. Not bad for a laptop that plays League of Legends at a choppy 30 FPS on medium graphics, while compiling and running Haskell unit tests in the background.