1
- Getting Started with Haskell and Cabal
2
- ======================================
1
+ Getting Started
2
+ ===============
3
3
4
- Installing the Haskell toolchain
5
- --------------------------------
6
-
7
- To install the Haskell toolchain follow the `ghcup instructions
8
- <https://www.haskell.org/ghcup/> `__.
4
+ Installing Cabal
5
+ ----------------
9
6
7
+ The easiest and recommended way to install the ``cabal `` command-line tool
8
+ on Linux, macOS, FreeBSD or Windows is through `ghcup <https://www.haskell.org/ghcup/ >`__.
9
+ It installs the “Haskell toolchain”, which includes Cabal,
10
+ the Haskell compiler `GHC <https://www.haskell.org/ghc/ >`__
11
+ and optionally other useful Haskell tools.
10
12
11
13
Creating a new application
12
14
--------------------------
13
15
14
- Let's start by creating a simple Haskell application from scratch where we'll
15
- learn about a Haskell package's directory structure, how to run the executable,
16
- and how to add external dependencies.
16
+ We create a minimal Haskell application to get a quick overview
17
+ of the ``cabal `` command-line tool:
17
18
19
+ 1. How to initialize a Haskell package.
20
+ 2. How files are organized inside a package.
21
+ 3. How to compile Haskell files and run a resulting executable.
22
+ 4. How to manage external dependencies.
18
23
19
- Initializing the application
20
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24
+ Initializing an application
25
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
21
26
22
- Start by initialising our ``myfirstapp `` project, these instructions work in
23
- unix shells and PowerShell (if you're on Windows).
27
+ To initialize a new Haskell application, run
24
28
25
29
.. code-block :: console
26
30
27
- $ cabal init myfirstapp -n
28
-
29
- .. note :: ``myfirstapp`` stands for the directory (or path) where the project
30
- will reside in, if omitted, ``cabal init `` will do its proceedings
31
- in the directory it's called in.
31
+ $ cabal init myapp --non-interactive
32
32
33
- .. note :: ``-n`` stands for ``--non-interactive``, which means that cabal will try to guess
34
- how to set up the project for you and use the default settings, which will serve us
35
- well for the purpose of this tutorial.
36
- When setting up your projects in the future, you will likely want to omit ``-n ``
37
- and do just ``cabal init ``, so that cabal will interactively ask you
38
- for the details on how the project should be set up
39
- (while still offering reasonable defaults on every step).
40
- Also, you can run ``cabal init --help `` to get more info on how ``cabal init `` can be used.
41
-
42
- This will generate the following files:
33
+ in a terminal. This generates the following files in a new ``myapp `` directory:
43
34
44
35
.. code-block :: console
45
36
46
37
$ tree
47
38
.
48
- └── myfirstapp
39
+ └── myapp
49
40
├── app
50
41
│ └── Main.hs
51
42
├── CHANGELOG.md
52
- └── myfirstapp .cabal
43
+ └── myapp .cabal
53
44
54
- `` app/Main.hs `` is where your package's code lives.
45
+ The `` myapp.cabal `` file is a package description file, commonly referred to as a “Cabal file”:
55
46
56
- ``myfirstapp.cabal `` is Cabal's metadata file which describes your package,
57
- how it is built and its dependencies. We'll be updating this file in a
58
- little bit when we add an external dependency to our package.
47
+ .. code-block :: cabal
59
48
49
+ cabal-version: 3.0
50
+ name: myapp
51
+ version: 0.1.0.0
52
+ -- ...
60
53
61
- Running the application
62
- ^^^^^^^^^^^^^^^^^^^^^^^
54
+ executable myapp
55
+ import: warnings
56
+ main-is: Main.hs
57
+ build-depends: base ^>=4.19.0.0
58
+ hs-source-dirs: app
59
+ default-language: Haskell2010
63
60
64
- When we ran ``cabal init myfirstapp -n `` above, it generated a package with a single
65
- executable named same as the package (in this case ``myfirstapp ``) that prints
66
- ``"Hello, Haskell!" `` to the terminal. To run the executable enter the project's
67
- directory and run it, by inputting the following commands:
61
+ It contains metadata (package name and version, author name, license, etc.) and sections
62
+ to define package components. Components can be used to split large codebases into smaller,
63
+ more managable building blocks.
64
+ A component can be of one of several types (executable, library, etc.) and describes,
65
+ among other things, the location of source files and its dependencies.
66
+ The ``myapp.cabal `` file above defines a single component named ``myapp `` of the executable type.
67
+ Inside the ``executable `` section, the ``build-depends `` field lists the dependencies of this component.
68
68
69
- .. code-block :: console
70
69
71
- cd myfirstapp
72
- cabal run myfirstapp
70
+ The ``app/Main.hs `` file is where your executable's code lives:
71
+
72
+ .. code-block :: haskell
73
73
74
- You should see the following output in the terminal:
74
+ module Main where
75
+
76
+ main :: IO ()
77
+ main = putStrLn "Hello, Haskell!"
78
+
79
+
80
+ To run the executable, switch into the application directory with ``cd myapp `` and run
75
81
76
82
.. code-block :: console
77
83
78
- $ cabal run myfirstapp
84
+ $ cabal run myapp
79
85
...
80
86
Hello, Haskell!
81
87
82
- Notice that we didn't need to run a `build ` command before we ran ``cabal run ``.
83
- This is because ``cabal run `` automatically determines if the code needs to be (re)built
84
- before running the executable.
85
- If you just want to build a target without running it, you can do so with ``cabal build ``:
88
+ This command automatically determines if the executable needs to be (re)built
89
+ before running the executable. With only one executable component in the package,
90
+ ``cabal run `` (without a component name) is smart enough to infer it, so the name can be omitted.
91
+
92
+ If you just want to build the executable without running it, run:
93
+
94
+ .. code-block :: console
86
95
87
- ``cabal build myfirstapp ``
96
+ $ cabal build
97
+ Resolving dependencies...
98
+ ...
99
+ Building executable 'myapp' for myapp-0.1.0.0..
100
+ [1 of 1] Compiling Main ( app/Main.hs, /home/.../myapp/dist-newstyle/build/.../myapp-tmp/Main.o )
101
+ Linking /home/.../myapp/dist-newstyle/build/.../myapp
88
102
89
103
90
104
Adding dependencies
@@ -103,16 +117,16 @@ terminal with some embellishment.
103
117
need to update the package index, you can do this by running ``cabal
104
118
update ``.
105
119
106
- In our ``myfirstapp .cabal `` file we'll update the ``build-depends `` attribute of
107
- the `` executable myfirstapp `` section to include ``haskell-say ``:
120
+ In our ``myapp .cabal `` file, we will update the ``build-depends `` field of
121
+ the executable section to include ``haskell-say ``:
108
122
109
123
.. code-block :: cabal
110
124
111
- executable myfirstapp
125
+ executable myapp
112
126
import: warnings
113
127
main-is: Main.hs
114
128
build-depends:
115
- base ^>=4.14.3 .0,
129
+ base ^>=4.19.0 .0,
116
130
haskell-say ^>=1.0.0.0
117
131
hs-source-dirs: app
118
132
default-language: Haskell2010
@@ -132,8 +146,7 @@ Next we'll update ``app/Main.hs`` to use the ``HaskellSay`` library:
132
146
import HaskellSay (haskellSay)
133
147
134
148
main :: IO ()
135
- main =
136
- haskellSay "Hello, Haskell! You're using a function from another package!"
149
+ main = haskellSay "Hello, Haskell!"
137
150
138
151
``import HaskellSay (haskellSay) `` brings the ``haskellSay `` function from the
139
152
module named ``HaskellSay `` into scope. The ``HaskellSay `` module is defined in
@@ -143,11 +156,10 @@ Now you can build and re-run your code to see the new output:
143
156
144
157
.. code-block :: console
145
158
146
- $ cabal run
159
+ $ cabal run myapp
147
160
________________________________________________________
148
161
/ \
149
- | Hello, Haskell! You're using a function from another |
150
- | package! |
162
+ | Hello, Haskell! |
151
163
\____ _____________________________________________/
152
164
\ /
153
165
\ /
@@ -166,42 +178,47 @@ Now you can build and re-run your code to see the new output:
166
178
/ / / / \ \
167
179
/____/ /____/ \____\
168
180
169
- Run a single-file Haskell script
170
- --------------------------------
181
+ Running a single-file Haskell script
182
+ ------------------------------------
171
183
172
- Cabal also enables us to run single-file Haskell scripts
173
- without creating a project directory or ``.cabal `` file.
174
- The cabal directives are placed in the file within a comment.
184
+ Cabal also supports running single-file Haskell scripts like
185
+ the following file named ``myscript ``:
175
186
176
187
.. code-block :: haskell
177
-
188
+
178
189
#!/usr/bin/env cabal
179
190
{- cabal:
180
- build-depends: base, split
191
+ build-depends:
192
+ base ^>=4.19.0.0,
193
+ haskell-say ^>=1.0.0.0
181
194
-}
182
195
183
- import Data.List.Split (chunksOf )
196
+ import HaskellSay (haskellSay )
184
197
185
198
main :: IO ()
186
- main = getLine >>= print . chunksOf 3
199
+ main = haskellSay "Hello, Haskell!"
187
200
188
- This can be run using ``cabal run myscript ``.
189
- On Unix-like systems this can be run directly with execute permission.
201
+ The necessary sections of a ``.cabal `` file are placed
202
+ directly into the script as a comment.
203
+
204
+ Use the familiar ``cabal run `` command to execute this script:
190
205
191
206
.. code-block :: console
192
207
193
208
$ cabal run myscript
194
209
195
- $ chmod +x myscript
196
- $ ./myscript
197
-
198
- Project metadata can also be included:
210
+ On Unix-like systems, a Haskell script starting with ``#!/usr/bin/env cabal ``, like the one above,
211
+ can be run directly after setting the execute permission (+x):
199
212
200
- .. code-block :: haskell
213
+ .. code-block :: console
201
214
202
- {- project:
203
- with-compiler: ghc-8.10.7
204
- -}
215
+ $ chmod +x myscript
216
+ $ ./myscript
217
+ ________________________________________________________
218
+ / \
219
+ | Hello, Haskell! |
220
+ \____ ____________________________________________/
221
+ \ ... /
205
222
206
223
See more in the documentation for :ref: `cabal run `.
207
224
0 commit comments