This commit is contained in:
Amy de Buitléir 2025-09-14 20:49:57 +01:00
parent a23029eb15
commit 00bfdf2c0f
12 changed files with 161 additions and 140 deletions

View file

@ -840,7 +840,8 @@ a path</code></pre>
</div>
<div class="paragraph">
<p>If an expression can be interpreted as a path, Nix will do so.
This is useful, because paths are <em>far</em> more commonly used in Nix expressions that arithmetic operators.
This is useful, because paths are <em>far</em> more commonly used in Nix expressions
than arithmetic operators.
In this case, Nix interpreted <code>6/2</code> as a relative path from the current directory,
which in the above example was <code>/home/amy/codeberg/nix-book</code>.</p>
</div>
@ -1617,9 +1618,9 @@ This is an important topic, so we will cover it separately in <a href="#argument
<p>To specify an attribute set as a function parameter, we use a <em>set pattern</em>,
which has the form</p>
</div>
<div class="literalblock">
<div class="listingblock">
<div class="content">
<pre class="nowrap">{ _name1_, _name2_, ... }</pre>
<pre class="pygments highlight nowrap"><code>{ <em>name1</em>, <em>name2</em>, ... }</code></pre>
</div>
</div>
<div class="paragraph">
@ -1858,9 +1859,10 @@ using the attribute selection operator (<code>.</code>).</p>
<div class="sectionbody">
<div class="paragraph">
<p>Before learning to write Nix flakes, let&#8217;s learn how to use them. I&#8217;ve
created a simple example of a flake in this git
<a href="https://codeberg.org/mhwombat/hello-flake">repository</a>. To run this
flake, you don&#8217;t need to install anything; simply run the command below.
created a simple example of a flake in this git repository:
<a href="https://codeberg.org/mhwombat/hello-flake" class="bare">https://codeberg.org/mhwombat/hello-flake</a>.
To run this flake, you don&#8217;t need to install anything;
simply run the command below.
The first time you use a flake, Nix has to fetch and build it, which
may take time. Subsequent invocations should be instantaneous.</p>
</div>
@ -1909,8 +1911,8 @@ directly available.</p>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ exit
$ hello-flake
sh: line 3: hello-flake: command not found</pre>
$ hello-flake # Won't work outside development shell
bash: line 24: hello-flake: command not found</pre>
</div>
</div>
<div class="paragraph">
@ -2028,13 +2030,7 @@ is always called <code>flake.nix</code>.</p>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-c1"># See https://github.com/mhwombat/nix-for-numbskulls/blob/main/flakes.md</span>
<span class="tok-c1"># for a brief overview of what each section in a flake should or can contain.</span>
<span class="normal">41</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">description</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;a very simple and friendly flake&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
@ -2081,7 +2077,7 @@ is always called <code>flake.nix</code>.</p>
<div class="paragraph">
<p>If this is your first time seeing a flake definition, it probably looks
intimidating.
Flakes are written in the Nix language, introduced in an earlier chapter.
Flakes are written in the Nix language, introduced in <a href="#_the_nix_language_">[_the_nix_language_]</a>.
However, you don&#8217;t really need to know Nix to follow this example.
For now, I&#8217;d like to focus on the inputs section.</p>
</div>
@ -2154,11 +2150,11 @@ flakes. The important thing to note is that the <code>hello-flake</code> package
&quot;systems&quot;: &quot;systems&quot;
},
&quot;locked&quot;: {
&quot;lastModified&quot;: 1681202837,
&quot;narHash&quot;: &quot;sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=&quot;,
&quot;lastModified&quot;: 1731533236,
&quot;narHash&quot;: &quot;sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=&quot;,
&quot;owner&quot;: &quot;numtide&quot;,
&quot;repo&quot;: &quot;flake-utils&quot;,
&quot;rev&quot;: &quot;cfacdce06f30d2b68473a46042957675eebb3401&quot;,
&quot;rev&quot;: &quot;11707dc2f618dd54ca8739b309ec4fc024de578b&quot;,
&quot;type&quot;: &quot;github&quot;
},
&quot;original&quot;: {
@ -2169,11 +2165,11 @@ flakes. The important thing to note is that the <code>hello-flake</code> package
},
&quot;nixpkgs&quot;: {
&quot;locked&quot;: {
&quot;lastModified&quot;: 1681665000,
&quot;narHash&quot;: &quot;sha256-hDGTR59wC3qrQZFxVi2U3vTY+r02+Okbq080hO1C4Nk=&quot;,
&quot;lastModified&quot;: 1757873102,
&quot;narHash&quot;: &quot;sha256-kYhNxLlYyJcUouNRazBufVfBInMWMyF+44xG/xar2yE=&quot;,
&quot;owner&quot;: &quot;NixOS&quot;,
&quot;repo&quot;: &quot;nixpkgs&quot;,
&quot;rev&quot;: &quot;3a6205d9f79fe526be03d8c465403b118ca4cf37&quot;,
&quot;rev&quot;: &quot;88cef159e47c0dc56f151593e044453a39a6e547&quot;,
&quot;type&quot;: &quot;github&quot;
},
&quot;original&quot;: {
@ -2509,41 +2505,12 @@ standard environment version), <code>developPackage</code>, <code>callCabal2Nix<
<p>Now that we have a better understanding of the structure of <code>flake.nix</code>,
let&#8217;s have a look at the one we saw earlier, in the <code>hello-flake</code> repo.
If you compare this flake definition to the colour-coded template
presented in the previous section, most of it should look familiar.</p>
presented in <a href="#_a_generic_flake">Chapter 6, <em>A generic flake</em></a>, most of it should look familiar.</p>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span><span class="tok-p">{</span>
<span class="tok-ss">description</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;a very simple and friendly flake&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
@ -2572,8 +2539,7 @@ presented in the previous section, most of it should look familiar.</p>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
<span class="tok-p">);</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
@ -2758,7 +2724,7 @@ so can&#8217;t we just run it?</p>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ hello-flake
Hello from your flake!</pre>
bash: line 16: hello-flake: command not found</pre>
</div>
</div>
<div class="paragraph">
@ -2860,7 +2826,7 @@ Here&#8217;s the modified <code>hello-flake</code> file.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ ./hello-flake
<pre class="nowrap">$ ./hello-flake # Won't work
./hello-flake: line 3: cowsay: command not found</pre>
</div>
</div>
@ -2991,7 +2957,7 @@ It&#8217;s just a warning, though; the script runs correctly.</p>
<pre class="nowrap">$ nix develop
warning: Git tree '/home/amy/codeberg/nix-book/source/modify-hello-flake/hello-flake' is dirty
$ which cowsay # is it available now?
/nix/store/gfi27h4y5n4aralcxrc0377p8mjb1cvb-cowsay-3.7.0/bin/cowsay
/nix/store/y5kz17amqc5gn1yvga9wj3vsjz8s1f0c-cowsay-3.8.4/bin/cowsay
$ ./hello-flake
________________________
&lt; Hello from your flake! &gt;
@ -3009,9 +2975,9 @@ $ exit</pre>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run
<pre class="nowrap">$ nix run # Won't work
warning: Git tree '/home/amy/codeberg/nix-book/source/modify-hello-flake/hello-flake' is dirty
/nix/store/7p4migpqjsr86xqj4dxlpvma3h3y2bzi-hello-flake/bin/hello-flake: line 3: cowsay: command not found</pre>
/nix/store/rnjqkk7a8sz6wrm1qb1hxssy7qlgaa85-hello-flake/bin/hello-flake: line 3: cowsay: command not found</pre>
</div>
</div>
<div class="paragraph">
@ -3151,7 +3117,7 @@ specifying the full path to cowsay.</p>
Haskell, Python, Java, C, C#, or Rust,
the language build system will usually do all that is required
to make the dependencies visible to the program at runtime.
In this case, adding the dependency to <code>buildInputs</code> is sufficient.</p>
In that case, adding the dependency to <code>buildInputs</code> is sufficient.</p>
</div>
</td>
</tr>
@ -3182,7 +3148,7 @@ we&#8217;ll see next.</p>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ cat result/bin/hello-flake
#!/nix/store/zlf0f88vj30sc7567b80l52d19pbdmy2-bash-5.2-p15/bin/sh
#!/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin/sh
echo "Hello from your flake!"</pre>
</div>
@ -3195,9 +3161,9 @@ echo "Hello from your flake!"</pre>
<pre class="nowrap">$ nix build
warning: Git tree '/home/amy/codeberg/nix-book/source/modify-hello-flake/hello-flake' is dirty
$ cat result/bin/hello-flake
#!/nix/store/zlf0f88vj30sc7567b80l52d19pbdmy2-bash-5.2-p15/bin/sh
#!/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin/sh
/nix/store/gfi27h4y5n4aralcxrc0377p8mjb1cvb-cowsay-3.7.0/bin/cowsay "Hello from your flake!"</pre>
/nix/store/y5kz17amqc5gn1yvga9wj3vsjz8s1f0c-cowsay-3.8.4/bin/cowsay "Hello from your flake!"</pre>
</div>
</div>
<div class="paragraph">
@ -3207,8 +3173,8 @@ don&#8217;t need to <code>git push</code> the changes until we&#8217;re ready to
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ git commit hello-flake flake.nix -m 'added bovine feature'
[main 6523897] added bovine feature
2 files changed, 13 insertions(+), 4 deletions(-)
[main a10700e] added bovine feature
2 files changed, 13 insertions(+), 1 deletion(-)
$ nix run
________________________
&lt; Hello from your flake! &gt;
@ -3416,7 +3382,7 @@ You can come back to this section later to learn more.</p>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix shell nixpkgs#ghc
$ runghc Main.hs
$ runghc Main.hs # Won't work
Main.hs:1:1: error: [GHC-87110]
Could not find module Network.HostName.
@ -3435,7 +3401,7 @@ Let&#8217;s exit that shell and try again, this time adding the <code>hostname</
<div class="content">
<pre class="nowrap">$ exit
$ nix shell nixpkgs#ghc nixpkgs#hostname
$ runghc Main.hs
$ runghc Main.hs # Won't work
Main.hs:1:1: error: [GHC-87110]
Could not find module Network.HostName.
@ -3458,7 +3424,7 @@ The package we want is in the <em>package set</em> called <code>haskellPackages<
<div class="content">
<pre class="nowrap">$ exit
$ nix shell nixpkgs#ghc nixpkgs#haskellPackages.hostname
$ runghc Main.hs
$ runghc Main.hs # Won't work
Main.hs:1:1: error: [GHC-87110]
Could not find module Network.HostName.
@ -3496,11 +3462,6 @@ Your hostname is: wombat11k</pre>
<div class="paragraph">
<p>Success! Now we know the program works.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ exit</pre>
</div>
</div>
</div>
</div>
<div class="sect3">
@ -3600,7 +3561,7 @@ First we&#8217;ll try building the package manually.
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ cabal build
sh: line 46: cabal: command not found</pre>
sh: line 42: cabal: command not found</pre>
</div>
</div>
<div class="paragraph">
@ -3808,9 +3769,9 @@ warning: creating lock file '"/home/amy/codeberg/nix-book/source/new-flake/haske
• Added input 'flake-parts/nixpkgs-lib':
'github:nix-community/nixpkgs.lib/a73b9c743612e4244d865a2fdee11865283c04e6?narHash=sha256-x2rJ%2BOvzq0sCMpgfgGaaqgBSwY%2BLST%2BWbZ6TytnT9Rk%3D' (2025-08-10)
• Added input 'haskell-flake':
'github:srid/haskell-flake/73e3891fb135c679a1c30fae4b101e5b41b8ca61?narHash=sha256-%2B99fEAk0HwjYgIW2tEOs7ayBDxnU9NAM5E29ZxgyX40%3D' (2025-08-31)
'github:srid/haskell-flake/2acbf1c9bb7aac38b59dcc3c1bd78911cf37e42c?narHash=sha256-jwZT6Ns4BXlrFHaXjZgZwfhSaw8nTCTKZ8fCDylrONM%3D' (2025-09-14)
• Added input 'nixpkgs':
'github:nixos/nixpkgs/c6a788f552b7b7af703b1a29802a7233c0067908?narHash=sha256-6n/n1GZQ/vi%2BLhFXMSyoseKdNfc2QQaSBXJdgamrbkE%3D' (2025-09-03)
'github:nixos/nixpkgs/6d7ec06d6868ac6d94c371458fc2391ded9ff13d?narHash=sha256-fEvTiU4s9lWgW7mYEU/1QUPirgkn%2BodUBTaindgiziY%3D' (2025-09-13)
warning: Git tree '/home/amy/codeberg/nix-book/source/new-flake/haskell-flake/hello-haskell' is dirty</pre>
</div>
</div>
@ -3847,7 +3808,7 @@ We need to add this to the repo, and commit all important files.</p>
<div class="content">
<pre class="nowrap">$ git add flake.lock
$ git commit -a -m 'initial commit'
[master (root-commit) d1f6c9b] initial commit
[master (root-commit) d35f8fd] initial commit
5 files changed, 170 insertions(+)
create mode 100644 LICENSE
create mode 100644 Main.hs
@ -4049,7 +4010,7 @@ First we&#8217;ll try building the package manually.
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ python -m build
<pre class="nowrap">$ python -m build # Won't work
/nix/store/iyff8129iampdw13nlfqalzhxy8y1hi9-python3-3.13.6/bin/python: No module named build</pre>
</div>
</div>
@ -4252,7 +4213,7 @@ something like this.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix build
<pre class="nowrap">$ nix build # Won't work
error: Path 'flake.nix' in the repository "/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python" is not tracked by Git.
To make it visible to Nix, run:
@ -4261,8 +4222,8 @@ error: Path 'flake.nix' in the repository "/home/amy/codeberg/nix-book/source/ne
</div>
</div>
<div class="paragraph">
<p>Why can&#8217;t it find <code>flake.nix</code>? Nix flakes only &#8220;see&#8221; files that are
part of the repository. We need to add all of the important files to the
<p>Nix flakes only &#8220;see&#8221; files that are part of the repository.
We need to add all of the important files to the
repo before building or running the flake.</p>
</div>
<div class="literalblock">
@ -4276,7 +4237,7 @@ warning: creating lock file '"/home/amy/codeberg/nix-book/source/new-flake/pytho
• Added input 'flake-utils/systems':
'github:nix-systems/default/da67096a3b9bf56a91d16901293e51ba5b49a27e?narHash=sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768%3D' (2023-04-09)
• Added input 'nixpkgs':
'github:NixOS/nixpkgs/9aaf71a4a74d835ec05ac3ddf5fc1b859e005c41?narHash=sha256-%2B0iaqsEjfaIZMuRNGO%2BwC0uVazT5b%2BW38wB7Uv0kA5Y%3D' (2025-09-06)
'github:NixOS/nixpkgs/5ad881b15fb2b63c2f127533ca59f840fcc24c3f?narHash=sha256-P8XdKg87fR5PpCjIgMH%2B05PDwhdmlNrigsvChdHfyaw%3D' (2025-09-14)
warning: Git tree '/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python' is dirty</pre>
</div>
</div>
@ -4312,7 +4273,7 @@ We need to add this to the repo, and commit all important files.</p>
<div class="content">
<pre class="nowrap">$ git add flake.lock
$ git commit -a -m 'initial commit'
[master (root-commit) 887d465] initial commit
[master (root-commit) 2af9bd5] initial commit
4 files changed, 127 insertions(+)
create mode 100644 flake.lock
create mode 100644 flake.nix
@ -4559,7 +4520,7 @@ However, you can use any of the flake reference styles defined in <a href="#flak
but you don&#8217;t want to bother writing a cabal file.</p>
</div>
<div class="paragraph">
<p>Example: Access the <code>containers</code> package from the <code>haskellPackages</code> set in the nixpkgs repo.</p>
<p>Example: Access the <code>extra</code> package from the <code>haskellPackages</code> set in the nixpkgs repo.</p>
</div>
<div class="listingblock">
<div class="title">Script</div>
@ -4573,36 +4534,24 @@ but you don&#8217;t want to bother writing a cabal file.</p>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-o">#!</span><span class="tok-w"> </span><span class="tok-o">/</span><span class="tok-n">usr</span><span class="tok-o">/</span><span class="tok-n">bin</span><span class="tok-o">/</span><span class="tok-n">env</span><span class="tok-w"> </span><span class="tok-n">nix</span><span class="tok-o">-</span><span class="tok-n">shell</span>
<span class="tok-o">#!</span><span class="tok-w"> </span><span class="tok-n">nix</span><span class="tok-o">-</span><span class="tok-n">shell</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-n">p</span><span class="tok-w"> </span><span class="tok-s">&quot;haskellPackages.ghcWithPackages (p: [p.containers])&quot;</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-o">#!</span><span class="tok-w"> </span><span class="tok-o">/</span><span class="tok-n">usr</span><span class="tok-o">/</span><span class="tok-n">bin</span><span class="tok-o">/</span><span class="tok-n">env</span><span class="tok-w"> </span><span class="tok-n">nix</span><span class="tok-o">-</span><span class="tok-n">shell</span>
<span class="tok-o">#!</span><span class="tok-w"> </span><span class="tok-n">nix</span><span class="tok-o">-</span><span class="tok-n">shell</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-n">p</span><span class="tok-w"> </span><span class="tok-s">&quot;haskellPackages.ghcWithPackages (p: [p.extra])&quot;</span>
<span class="tok-o">#!</span><span class="tok-w"> </span><span class="tok-n">nix</span><span class="tok-o">-</span><span class="tok-n">shell</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-n">i</span><span class="tok-w"> </span><span class="tok-n">runghc</span>
<span class="tok-kr">import</span><span class="tok-w"> </span><span class="tok-nn">Data.Map</span>
<span class="tok-nf">m</span><span class="tok-w"> </span><span class="tok-ow">::</span><span class="tok-w"> </span><span class="tok-kt">Map</span><span class="tok-w"> </span><span class="tok-kt">String</span><span class="tok-w"> </span><span class="tok-kt">Int</span>
<span class="tok-nf">m</span><span class="tok-w"> </span><span class="tok-ow">=</span><span class="tok-w"> </span><span class="tok-n">fromList</span><span class="tok-w"> </span><span class="tok-p">[(</span><span class="tok-s">&quot;cats&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-p">),</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-s">&quot;dogs&quot;</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-p">)]</span>
<span class="tok-kr">import</span><span class="tok-w"> </span><span class="tok-nn">Data.List.Extra</span>
<span class="tok-nf">main</span><span class="tok-w"> </span><span class="tok-ow">::</span><span class="tok-w"> </span><span class="tok-kt">IO</span><span class="tok-w"> </span><span class="tok-nb">()</span>
<span class="tok-nf">main</span><span class="tok-w"> </span><span class="tok-ow">=</span><span class="tok-w"> </span><span class="tok-kr">do</span>
<span class="tok-w"> </span><span class="tok-kr">let</span><span class="tok-w"> </span><span class="tok-n">cats</span><span class="tok-w"> </span><span class="tok-ow">=</span><span class="tok-w"> </span><span class="tok-n">findWithDefault</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-w"> </span><span class="tok-s">&quot;cats&quot;</span><span class="tok-w"> </span><span class="tok-n">m</span>
<span class="tok-w"> </span><span class="tok-kr">let</span><span class="tok-w"> </span><span class="tok-n">dogs</span><span class="tok-w"> </span><span class="tok-ow">=</span><span class="tok-w"> </span><span class="tok-n">findWithDefault</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-w"> </span><span class="tok-s">&quot;dogs&quot;</span><span class="tok-w"> </span><span class="tok-n">m</span>
<span class="tok-w"> </span><span class="tok-kr">let</span><span class="tok-w"> </span><span class="tok-n">zebras</span><span class="tok-w"> </span><span class="tok-ow">=</span><span class="tok-w"> </span><span class="tok-n">findWithDefault</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-w"> </span><span class="tok-s">&quot;zebras&quot;</span><span class="tok-w"> </span><span class="tok-n">m</span>
<span class="tok-w"> </span><span class="tok-n">print</span><span class="tok-w"> </span><span class="tok-o">$</span><span class="tok-w"> </span><span class="tok-s">&quot;I have &quot;</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-w"> </span><span class="tok-n">show</span><span class="tok-w"> </span><span class="tok-n">cats</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-w"> </span><span class="tok-s">&quot; cats, &quot;</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-w"> </span><span class="tok-n">show</span><span class="tok-w"> </span><span class="tok-n">dogs</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-w"> </span><span class="tok-s">&quot; dogs, and &quot;</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-w"> </span><span class="tok-n">show</span><span class="tok-w"> </span><span class="tok-n">zebras</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-w"> </span><span class="tok-s">&quot; zebras.&quot;</span>
<span class="tok-w"> </span><span class="tok-n">print</span><span class="tok-w"> </span><span class="tok-o">$</span><span class="tok-w"> </span><span class="tok-n">lower</span><span class="tok-w"> </span><span class="tok-s">&quot;ABCDE&quot;</span>
<span class="tok-w"> </span><span class="tok-n">print</span><span class="tok-w"> </span><span class="tok-o">$</span><span class="tok-w"> </span><span class="tok-n">upper</span><span class="tok-w"> </span><span class="tok-s">&quot;XYZ&quot;</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="literalblock">
<div class="title">Output</div>
<div class="content">
<pre class="nowrap">this path will be fetched (141.61 MiB download, 1821.03 MiB unpacked):
/nix/store/w6awqpzhn1pmfzql7ba5ar8pvs0yq5s2-ghc-9.8.4
copying path '/nix/store/w6awqpzhn1pmfzql7ba5ar8pvs0yq5s2-ghc-9.8.4' from 'https://cache.nixos.org'...
"I have 3 cats, 2 dogs, and 0 zebras."</pre>
<pre class="nowrap">"abcde"
"XYZ"</pre>
</div>
</div>
</div>
@ -4855,7 +4804,7 @@ In this example, we will access the <code>extra</code> package from the <code>ha
<div class="paragraph">
<p>For non-trivial Haskell development projects,
it&#8217;s usually more convenient to use <code>haskell-flake</code> as described in <a href="#haskell-flake">Section 9.1.5, &#8220;The Nix flake&#8221;</a>,
together with the high-level workflow described in <a href="#_development_workflows">Section 8.3, &#8220;Development workflows&#8221;</a>.</p>
together with the <em>high-level workflow</em> described in <a href="#_development_workflows">Section 8.3, &#8220;Development workflows&#8221;</a>.</p>
</div>
</td>
</tr>
@ -5649,7 +5598,7 @@ Hello from your flake!</pre>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2025-09-14 18:38:17 IST
Last updated 2025-09-14 20:47:54 IST
</div>
</div>
</body>

View file

@ -44,7 +44,7 @@ $# cat flake.nix
If this is your first time seeing a flake definition, it probably looks
intimidating.
Flakes are written in the Nix language, introduced in an earlier chapter.
Flakes are written in the Nix language, introduced in <<_the_nix_language_>>.
However, you don't really need to know Nix to follow this example.
For now, I'd like to focus on the inputs section.

View file

@ -3,9 +3,10 @@
Now that we have a better understanding of the structure of `flake.nix`,
let's have a look at the one we saw earlier, in the `hello-flake` repo.
If you compare this flake definition to the colour-coded template
presented in the previous section, most of it should look familiar.
presented in <<_a_generic_flake>>, most of it should look familiar.
[source,nix,linenums]
// don't use linenums because part of the file is omitted
[source,nix]
.flake.nix
....
{
@ -48,7 +49,8 @@ additional development tools.
Now let's look at the section I labeled `SOME UNFAMILIAR STUFF` and
see what it does.
[source,nix,linenums,subs=quotes]
// don't use linenums because part of the file is omitted
[source,nix,subs=quotes]
....
packages = rec {
hello = pkgs.stdenv.mkDerivation rec { ❶

View file

@ -1,11 +1,10 @@
= Hello, flake!
// TODO Need an intro explaining what flakes are. Move the "why flakes" section here.
Before learning to write Nix flakes, let's learn how to use them. I've
created a simple example of a flake in this git
https://codeberg.org/mhwombat/hello-flake[repository]. To run this
flake, you don't need to install anything; simply run the command below.
created a simple example of a flake in this git repository:
https://codeberg.org/mhwombat/hello-flake.
To run this flake, you don't need to install anything;
simply run the command below.
The first time you use a flake, Nix has to fetch and build it, which
may take time. Subsequent invocations should be instantaneous.

View file

@ -99,7 +99,7 @@ $# cat hello-flake
Let's test the modified script.
....
$ ./hello-flake
$ ./hello-flake # Won't work
....
What went wrong? Remember that we are in a _development_ shell. Since
@ -140,7 +140,7 @@ $ exit
Let's try `nix run`.
....
$ nix run
$ nix run # Won't work
....
What went wrong?
@ -171,7 +171,7 @@ When you're packaging a program written in a more powerful language such as
Haskell, Python, Java, C, C#, or Rust,
the language build system will usually do all that is required
to make the dependencies visible to the program at runtime.
In this case, adding the dependency to `buildInputs` is sufficient.
In that case, adding the dependency to `buildInputs` is sufficient.
====
This time `nix run` works.

View file

@ -70,7 +70,7 @@ Let's enter a shell with the Glasgow Haskell Compiler ("ghc") and try to run the
....
$# echo '$ nix shell nixpkgs#ghc'
$# nix shell nixpkgs#ghc --command sh
$ runghc Main.hs
$ runghc Main.hs # Won't work
....
The error message tells us that we need the module `Network.HostName`.
@ -81,7 +81,7 @@ Let's exit that shell and try again, this time adding the `hostname` package.
$# echo '$ exit'
$# echo '$ nix shell nixpkgs#ghc nixpkgs#hostname'
$# nix shell nixpkgs#ghc nixpkgs#hostname --command sh
$ runghc Main.hs
$ runghc Main.hs # Won't work
....
That reason that failed is that we asked for the wrong package.
@ -95,7 +95,7 @@ Let's try that again, with the correct package.
$# echo '$ exit'
$# echo '$ nix shell nixpkgs#ghc nixpkgs#haskellPackages.hostname'
$# nix shell nixpkgs#ghc nixpkgs#haskellPackages.hostname --command sh
$ runghc Main.hs
$ runghc Main.hs # Won't work
....
Now what's wrong?
@ -121,10 +121,6 @@ $ runghc Main.hs
Success! Now we know the program works.
....
$# echo '$ exit'
....
== The cabal file
It's time to write a Cabal file for this program.

View file

@ -101,7 +101,7 @@ We won't write `flake.nix` just yet.
First we'll try building the package manually.
(If you didn't run the `nix shell` command from <<python-nix-shell,earlier>>, do so now.)
....
$ python -m build
$ python -m build # Won't work
....
The missing module error happens because we don't have `build` available
@ -198,11 +198,11 @@ $# cat flake.nix
Let's try out the new flake.
....
$ nix build
$ nix build # Won't work
....
Why can't it find `flake.nix`? Nix flakes only "`see`" files that are
part of the repository. We need to add all of the important files to the
Nix flakes only "`see`" files that are part of the repository.
We need to add all of the important files to the
repo before building or running the flake.
....

View file

@ -19,7 +19,7 @@ $# cat flake.nix
Here's a demonstration using the shell.
....
$ cowsay "Moo!"
$ cowsay "Moo!" # Won't work; dependency not available
$# ../../../../../start-shell nix develop <<EOL
$ cowsay "Moo!"
$# EOL

View file

@ -0,0 +1,60 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1757876592,
"narHash": "sha256-P8XdKg87fR5PpCjIgMH+05PDwhdmlNrigsvChdHfyaw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5ad881b15fb2b63c2f127533ca59f840fcc24c3f",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -0,0 +1,20 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
in
{
devShells = rec {
default = pkgs.mkShell {
packages = [ pkgs.cowsay ];
};
};
}
);
}

View file

@ -3,7 +3,7 @@
Occasionally you might want to run a short Haskell program that depends on a Haskell library,
but you don't want to bother writing a cabal file.
Example: Access the `containers` package from the `haskellPackages` set in the nixpkgs repo.
Example: Access the `extra` package from the `haskellPackages` set in the nixpkgs repo.
[source,haskell,linenums]
.Script

View file

@ -1,15 +1,10 @@
#! /usr/bin/env nix-shell
#! nix-shell -p "haskellPackages.ghcWithPackages (p: [p.containers])"
#! nix-shell -p "haskellPackages.ghcWithPackages (p: [p.extra])"
#! nix-shell -i runghc
import Data.Map
m :: Map String Int
m = fromList [("cats", 3), ("dogs", 2)]
import Data.List.Extra
main :: IO ()
main = do
let cats = findWithDefault 0 "cats" m
let dogs = findWithDefault 0 "dogs" m
let zebras = findWithDefault 0 "zebras" m
print $ "I have " ++ show cats ++ " cats, " ++ show dogs ++ " dogs, and " ++ show zebras ++ " zebras."
print $ lower "ABCDE"
print $ upper "XYZ"