Paluu Haskelliin, osa 1
Kävin muutama vuosi sitten Haskell-ohjelmointikurssin, jota pidin todella mielenkiintoisena, mutta kielen käyttö jäi sikseen – käytön jatkamiselle ei löytynyt syitä. Haluan nyt tehdä asiaan muutoksen. Suunnitelmani on rakentaa šakkiohjelma, ei maailmanluokan sellainen mutta kuitenkin täysin toimiva, kaikilla säännöillä ja riittävän vahvana, jotta se osaisi minut päihittää. (Olen shakin suhteen amatööri.)
Käymäni kurssin materiaali suositteli Haskell Tool Stack -työkalua, ja aion sitä käyttää nytkin. Ehdotettu asennustapa *nix-järjestelmille, jossa ohjeiden mukaan haetaan skripti curlilla ja putkitetaan sh:lle, vaikuttaa hieman riskikkäältä mutta lukaistuni läpi 805-rivisen skriptin ajan sen.
curl -sSL https://get.haskellstack.org/ | sh
Testaan asennuksen pikaisesti komentorivitulkilla, ajamalla stack ghci ja alla olevilla syötteillä. GHC on aika iso, parisataa megatavua.
Prelude> luku = 30
Prelude> luku
30
Prelude> successor = \n -> n + 1
Prelude> successor luku
31
Prelude> successor successor luku
<interactive>:5:1: error:
• Non type-variable argument in the constraint: Num (a -> a)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a. (Num a, Num (a -> a)) => a
Prelude> successor $ successor luku
32
Stackin dokumentaatio ehdottaa kokonaisen projektihakemistopuun luontia, joka ei nyt houkuta näin pienellä projektilla, joten skippaan sen ja luon vain tiedoston Chess.hs. Asennukseni testaamiseksi lisään sinne muutaman yksinkertaisen funktion, kurssin koodausharjoituksista:
module Chess where
double :: Integer -> Integer
double n = 2 * n
factorial :: Integer -> Integer
factorial n = if n <= 0
then 1
else n * factorial (n - 1)
tribonacci :: Integer -> Integer
tribonacci n = tribonacci' 0 0 1 n
tribonacci' :: Integer -> Integer -> Integer -> Integer -> Integer
tribonacci' _ _ c 1 = c
tribonacci' a b c n = tribonacci' b c (a+b+c) (n-1)
Ja ajoin interaktiivisen tulkin, jossa pääsin tätä testaamaan:
$ stack ghci Chess.hs [...] [1 of 1] Compiling Chess ( /.../Chess.hs, interpreted ) Ok, one module loaded. [...] *Chess> double 30 60 *Chess> factorial 10 3628800 *Chess> take 20 (iterate (\n -> n + 1) 1) [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] *Chess> map tribonacci $ take 15 (iterate (\n -> n + 1) 1) [1,1,2,4,7,13,24,44,81,149,274,504,927,1705,3136,5768]
Aion projektissani käyttää vain "standardikirjastoa" eli Prelude-moduulia, niin pitkälti kuin mahdollista. Shakin toteutus alkaa osassa 2.