Overview
This section is a walkthrough of a project with the code intended to display how to write a simple but real-world application in Haskell.
The subsections are ordered by difficulty.
The code is written for the compiler version GHC 9.2.5. Getting set up is easy!
Tip
We strongly encourage reading Haskell code in a text editor with the IDE activated: mousing over variables will show their type and where they are defined, which is especially helpful when learning. Cmd + click
to jump to a definition.
Demo:¶
cabal run chess-repl
Welcome!
>
place a white bishop on a5
_|_|_|_|b|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
>
place a black castle on b6
1:15:
|
1 | place a black castle on b6
| ^^^^^^
unexpected "castle"
expecting "bishop", "king", "knight", "pawn", "queen", "rook", or white space
>
:d
_|_|_|_|b|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_
>
:q
Tip
If you encounter an expression in this codebase that you don't understand, use Haskell's purity and immutability to your advantage: you can't always break it down into its parts and understand them separately.
main :: IO ()
main = runInputT defaultSettings $ flip evalStateT initBoard $ forever $ do
line <- lift requestLine
...
Break this down by replacing everything after the first or second dollar sign with undefined
, and then mouse over undefined
to understand its type:
Or
Or remove everything before the first or second dollar sign and have Haskell infer the type:
-- main :: IO () -- commented out since the type might be different now
main = flip evalStateT initBoard $ forever $ do
line <- lift requestLine
...
Consider this the Haskell debugging analogue of inserting print statements.
Created: January 8, 2023