mirror of
https://github.com/iritmaximus/haskell.git
synced 2026-10-12 19:13:39 +03:00
use simpler x = y syntax in GHCi
instead of let x = y
This commit is contained in:
+12
-12
@@ -1548,7 +1548,7 @@ pit----->|Room "You fall..." []| treasure--->|Room "A gr
|
||||
<span id="cb112-14"><a href="#cb112-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- and so on</span></span></code></pre></div>
|
||||
<p>A ha! The problem is that our recursion base case of <code>sumEverySecond 0</code> is not enough to stop the recursion.</p>
|
||||
<p>Finally, a word of caution. Using <code>trace</code>, and especially <code>traceShowId</code>, can cause things that would not otherwise get evaluated to get evaluated. For example:</p>
|
||||
<div class="sourceCode" id="cb113"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb113-1"><a href="#cb113-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Debug.Trace</span><span class="op">></span> <span class="kw">let</span> traceHead xs <span class="ot">=</span> <span class="fu">head</span> (traceShowId xs)</span>
|
||||
<div class="sourceCode" id="cb113"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb113-1"><a href="#cb113-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Debug.Trace</span><span class="op">></span> traceHead xs <span class="ot">=</span> <span class="fu">head</span> (traceShowId xs)</span>
|
||||
<span id="cb113-2"><a href="#cb113-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Debug.Trace</span><span class="op">></span> traceHead [<span class="dv">0</span><span class="op">..</span>]</span>
|
||||
<span id="cb113-3"><a href="#cb113-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- never terminates since it's trying to show an infinite list</span></span></code></pre></div>
|
||||
<p>So feel free to use <code>Debug.Trace</code> when working on the exercises, but try to leave <code>trace</code> calls out of your final answers. Some exercise sets check your imports and disallow <code>Debug.Trace</code>.</p>
|
||||
@@ -2089,10 +2089,10 @@ Prelude> final
|
||||
<h2 data-number="11.8"><span class="header-section-number">11.8</span> What Does It All Mean?</h2>
|
||||
<p>Let’s return to the functional world. How can we reconcile IO operations with Haskell being a <em>pure</em> and <em>lazy</em> language? Something like <code>putStrLn :: String -> IO ()</code> is a <em>pure</em> function that returns an operation. How is it pure? <code>putStrLn x</code> is the same when <code>x</code> is the same. In other words: an operation is a <em>pure description</em> of a chain of side effects. Only <em>executing</em> the operation causes those side effects. When a Haskell program is run, only one operation is executed - it’s called <code>main :: IO ()</code>. Other operations can be run only by linking them up to <code>main</code>.</p>
|
||||
<p>When in GHCi, if an expression you type in evaluates to an operation, GHCi runs that operation for you. Here’s a demonstration of the purity of <code>print</code>:</p>
|
||||
<div class="sourceCode" id="cb163"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb163-1"><a href="#cb163-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> <span class="kw">let</span> x <span class="ot">=</span> <span class="fu">print</span> <span class="dv">1</span> <span class="co">-- creates operation, doesn't run it</span></span>
|
||||
<span id="cb163-2"><a href="#cb163-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> x <span class="co">-- runs the operation</span></span>
|
||||
<div class="sourceCode" id="cb163"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb163-1"><a href="#cb163-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> x <span class="ot">=</span> <span class="fu">print</span> <span class="dv">1</span> <span class="co">-- creates operation, doesn't run it</span></span>
|
||||
<span id="cb163-2"><a href="#cb163-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> x <span class="co">-- runs the operation</span></span>
|
||||
<span id="cb163-3"><a href="#cb163-3" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span></span>
|
||||
<span id="cb163-4"><a href="#cb163-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> x <span class="co">-- runs it again!</span></span>
|
||||
<span id="cb163-4"><a href="#cb163-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> x <span class="co">-- runs it again!</span></span>
|
||||
<span id="cb163-5"><a href="#cb163-5" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span></span></code></pre></div>
|
||||
<p><em>Operations are values</em> just like numbers, lists and functions. We can write code that operates on operations. This function takes two operations, <code>a</code> and <code>b</code>, and returns an operation that asks the user which one he’d like to run.</p>
|
||||
<div class="sourceCode" id="cb164"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb164-1"><a href="#cb164-1" aria-hidden="true" tabindex="-1"></a><span class="ot">choice ::</span> <span class="dt">IO</span> x <span class="ot">-></span> <span class="dt">IO</span> x <span class="ot">-></span> <span class="dt">IO</span> x</span>
|
||||
@@ -2910,7 +2910,7 @@ this topic connects to equational reasoning discussed in chapter 10.
|
||||
<span id="cb232-32"><a href="#cb232-32" aria-hidden="true" tabindex="-1"></a><span class="ot">withdrawOp ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">Int</span> <span class="ot">-></span> <span class="dt">BankOp</span> <span class="dt">Int</span></span>
|
||||
<span id="cb232-33"><a href="#cb232-33" aria-hidden="true" tabindex="-1"></a>withdrawOp accountName amount <span class="ot">=</span> <span class="dt">BankOp</span> (withdraw accountName amount)</span></code></pre></div>
|
||||
<p>Let’s see how chaining works with these bank operations.</p>
|
||||
<div class="sourceCode" id="cb233"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb233-1"><a href="#cb233-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> <span class="kw">let</span> bank <span class="ot">=</span> <span class="dt">Bank</span> (Map.fromList [(<span class="st">"edsger"</span>,<span class="dv">10</span>),(<span class="st">"grace"</span>,<span class="dv">50</span>)])</span>
|
||||
<div class="sourceCode" id="cb233"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb233-1"><a href="#cb233-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> bank <span class="ot">=</span> <span class="dt">Bank</span> (Map.fromList [(<span class="st">"edsger"</span>,<span class="dv">10</span>),(<span class="st">"grace"</span>,<span class="dv">50</span>)])</span>
|
||||
<span id="cb233-2"><a href="#cb233-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb233-3"><a href="#cb233-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- Running a number of operations using +>></span></span>
|
||||
<span id="cb233-4"><a href="#cb233-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||
@@ -3580,7 +3580,7 @@ None of the above
|
||||
<div class="sourceCode" id="cb311"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb311-1"><a href="#cb311-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> <span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Text</span> <span class="kw">as</span> <span class="dt">T</span></span>
|
||||
<span id="cb311-2"><a href="#cb311-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span><span class="op">></span> <span class="op">:</span>t T.pack</span>
|
||||
<span id="cb311-3"><a href="#cb311-3" aria-hidden="true" tabindex="-1"></a>T.pack<span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-></span> <span class="dt">T.Text</span></span>
|
||||
<span id="cb311-4"><a href="#cb311-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span><span class="op">></span> <span class="kw">let</span> phrase <span class="ot">=</span> T.pack <span class="st">"brevity is the soul of wit"</span></span>
|
||||
<span id="cb311-4"><a href="#cb311-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span><span class="op">></span> phrase <span class="ot">=</span> T.pack <span class="st">"brevity is the soul of wit"</span></span>
|
||||
<span id="cb311-5"><a href="#cb311-5" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span><span class="op">></span> <span class="op">:</span>t phrase</span>
|
||||
<span id="cb311-6"><a href="#cb311-6" aria-hidden="true" tabindex="-1"></a><span class="ot">phrase ::</span> <span class="dt">T.Text</span></span>
|
||||
<span id="cb311-7"><a href="#cb311-7" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span><span class="op">></span> phrase</span>
|
||||
@@ -3626,7 +3626,7 @@ None of the above
|
||||
<span id="cb316-4"><a href="#cb316-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span> <span class="dt">TL</span><span class="op">></span> TL.head (TL.pack (<span class="fu">repeat</span> <span class="ch">'x'</span>))</span>
|
||||
<span id="cb316-5"><a href="#cb316-5" aria-hidden="true" tabindex="-1"></a><span class="ch">'x'</span></span></code></pre></div>
|
||||
<p>Another practical problem that sometimes crops is that you can end up with a mismatch between strict and lazy <code>Text</code>s when using libraries. You can usually fix this by using <code>toStrict</code> or <code>fromStrict</code> as needed.</p>
|
||||
<div class="sourceCode" id="cb317"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb317-1"><a href="#cb317-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span> <span class="dt">TL</span><span class="op">></span> <span class="kw">let</span> lazyPhrase <span class="ot">=</span> TL.pack <span class="st">"brevity is the soul of wit"</span></span>
|
||||
<div class="sourceCode" id="cb317"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb317-1"><a href="#cb317-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span> <span class="dt">TL</span><span class="op">></span> lazyPhrase <span class="ot">=</span> TL.pack <span class="st">"brevity is the soul of wit"</span></span>
|
||||
<span id="cb317-2"><a href="#cb317-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span> <span class="dt">TL</span><span class="op">></span> <span class="op">:</span>t lazyPhrase</span>
|
||||
<span id="cb317-3"><a href="#cb317-3" aria-hidden="true" tabindex="-1"></a><span class="ot">lazyPhrase ::</span> <span class="dt">TL.Text</span></span>
|
||||
<span id="cb317-4"><a href="#cb317-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">T</span> <span class="dt">TL</span><span class="op">></span> <span class="op">:</span>t phrase</span>
|
||||
@@ -3655,7 +3655,7 @@ None of the above
|
||||
<p>We can walk through pretty much the same GHCi session using <code>ByteString</code> instead of <code>Text</code>. However, note how the <code>ByteString</code> is built up from <code>Word8</code> values and not <code>Char</code> values. A <code>Char</code> can represent an arbitrary unicode codepoint like for a character like <code>'Å'</code>, but a <code>Word8</code> represents a byte: a number from 0 to 255. Unfortunately and somewhat confusingly, <code>ByteString</code> values get printed like <code>String</code>s.</p>
|
||||
<div class="sourceCode" id="cb318"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb318-1"><a href="#cb318-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> <span class="kw">import</span> <span class="dt">Data.Word</span></span>
|
||||
<span id="cb318-2"><a href="#cb318-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Data.Word</span><span class="op">></span> <span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">B</span></span>
|
||||
<span id="cb318-3"><a href="#cb318-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Data.Word</span> <span class="dt">B</span><span class="op">></span> <span class="kw">let</span> binary <span class="ot">=</span> B.pack [<span class="dv">99</span>,<span class="dv">111</span>,<span class="dv">102</span>,<span class="dv">102</span>,<span class="dv">101</span>,<span class="dv">101</span>]</span>
|
||||
<span id="cb318-3"><a href="#cb318-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Data.Word</span> <span class="dt">B</span><span class="op">></span> binary <span class="ot">=</span> B.pack [<span class="dv">99</span>,<span class="dv">111</span>,<span class="dv">102</span>,<span class="dv">102</span>,<span class="dv">101</span>,<span class="dv">101</span>]</span>
|
||||
<span id="cb318-4"><a href="#cb318-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Data.Word</span> <span class="dt">B</span><span class="op">></span> <span class="op">:</span>t binary</span>
|
||||
<span id="cb318-5"><a href="#cb318-5" aria-hidden="true" tabindex="-1"></a><span class="ot">binary ::</span> <span class="dt">B.ByteString</span></span>
|
||||
<span id="cb318-6"><a href="#cb318-6" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Data.Word</span> <span class="dt">B</span><span class="op">></span> <span class="op">:</span>t B.pack</span>
|
||||
@@ -3825,7 +3825,7 @@ None of the above
|
||||
<span id="cb328-5"><a href="#cb328-5" aria-hidden="true" tabindex="-1"></a> <span class="co">-- Defined in ‘Database.SQLite.Simple.Types’</span></span>
|
||||
<span id="cb328-6"><a href="#cb328-6" aria-hidden="true" tabindex="-1"></a> <span class="co">-- ... rest of output omitted</span></span>
|
||||
<span id="cb328-7"><a href="#cb328-7" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span><span class="op">></span> <span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Text</span> <span class="kw">as</span> <span class="dt">T</span></span>
|
||||
<span id="cb328-8"><a href="#cb328-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> <span class="kw">let</span> q <span class="ot">=</span> <span class="dt">Query</span> (T.pack <span class="st">"SELECT 1;"</span>)</span>
|
||||
<span id="cb328-8"><a href="#cb328-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> q <span class="ot">=</span> <span class="dt">Query</span> (T.pack <span class="st">"SELECT 1;"</span>)</span>
|
||||
<span id="cb328-9"><a href="#cb328-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> res <span class="ot"><-</span> query_ db<span class="ot"> q ::</span> <span class="dt">IO</span> [[<span class="dt">Int</span>]]</span>
|
||||
<span id="cb328-10"><a href="#cb328-10" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> res</span>
|
||||
<span id="cb328-11"><a href="#cb328-11" aria-hidden="true" tabindex="-1"></a>[[<span class="dv">1</span>]]</span></code></pre></div>
|
||||
@@ -3847,7 +3847,7 @@ None of the above
|
||||
<span id="cb330-6"><a href="#cb330-6" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">FromField</span> a, <span class="dt">FromField</span> b) <span class="ot">=></span> <span class="dt">FromRow</span> (a,b)</span>
|
||||
<span id="cb330-7"><a href="#cb330-7" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">FromField</span> a, <span class="dt">FromField</span> b, <span class="dt">FromField</span> c) <span class="ot">=></span> <span class="dt">FromRow</span> (a,b,c)</span></code></pre></div>
|
||||
<p>In essence, basic Haskell datatypes fulfill the <code>FromField</code> class, and various Haskell collections fulfill the <code>FromRow</code> class. Our earlier example was using the <code>FromRow [a]</code> and <code>FromField Int</code> instances to get a <code>[[Int]]</code> out of <code>query_</code>. Here’s a simple query that uses some other datatypes:</p>
|
||||
<div class="sourceCode" id="cb331"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb331-1"><a href="#cb331-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> <span class="kw">let</span> q <span class="ot">=</span> <span class="dt">Query</span> (T.pack <span class="st">"SELECT 1, true, 'string';"</span>)</span>
|
||||
<div class="sourceCode" id="cb331"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb331-1"><a href="#cb331-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> q <span class="ot">=</span> <span class="dt">Query</span> (T.pack <span class="st">"SELECT 1, true, 'string';"</span>)</span>
|
||||
<span id="cb331-2"><a href="#cb331-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> query_ db<span class="ot"> q ::</span> <span class="dt">IO</span> [(<span class="dt">Int</span>,<span class="dt">Bool</span>,<span class="dt">String</span>)]</span>
|
||||
<span id="cb331-3"><a href="#cb331-3" aria-hidden="true" tabindex="-1"></a>[(<span class="dv">1</span>,<span class="dt">True</span>,<span class="st">"string"</span>)]</span></code></pre></div>
|
||||
<p>What happens if the SQL and Haskell types don’t match? Well, you get a runtime error, just like if you try to invoke <code>read "True" :: Int</code>.</p>
|
||||
@@ -3867,8 +3867,8 @@ None of the above
|
||||
<span id="cb334-9"><a href="#cb334-9" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">ToField</span> a, <span class="dt">ToField</span> b, <span class="dt">ToField</span> c) <span class="ot">=></span> <span class="dt">ToRow</span> (a, b, c)</span></code></pre></div>
|
||||
<!-- instance ToField a => ToField (Maybe a) -- TODO talk about sql null -->
|
||||
<p>Parameterized queries use a <code>?</code> character to denote slots where parameters can be passed in. Here’s a simple example:</p>
|
||||
<div class="sourceCode" id="cb335"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb335-1"><a href="#cb335-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> <span class="kw">let</span> input <span class="ot">=</span> (<span class="dv">1</span>,<span class="st">"hello"</span>)<span class="ot"> ::</span> (<span class="dt">Int</span>,<span class="dt">String</span>)</span>
|
||||
<span id="cb335-2"><a href="#cb335-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> <span class="kw">let</span> parameterized <span class="ot">=</span> <span class="dt">Query</span> (T.pack <span class="st">"SELECT ?+1, true, ?;"</span>)</span>
|
||||
<div class="sourceCode" id="cb335"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb335-1"><a href="#cb335-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> input <span class="ot">=</span> (<span class="dv">1</span>,<span class="st">"hello"</span>)<span class="ot"> ::</span> (<span class="dt">Int</span>,<span class="dt">String</span>)</span>
|
||||
<span id="cb335-2"><a href="#cb335-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> parameterized <span class="ot">=</span> <span class="dt">Query</span> (T.pack <span class="st">"SELECT ?+1, true, ?;"</span>)</span>
|
||||
<span id="cb335-3"><a href="#cb335-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span> <span class="dt">T</span><span class="op">></span> query db parameterized<span class="ot"> input ::</span> <span class="dt">IO</span> [(<span class="dt">Int</span>,<span class="dt">Bool</span>,<span class="dt">String</span>)]</span>
|
||||
<span id="cb335-4"><a href="#cb335-4" aria-hidden="true" tabindex="-1"></a>[(<span class="dv">2</span>,<span class="dt">True</span>,<span class="st">"hello"</span>)]</span></code></pre></div>
|
||||
<p>That’s pretty much all you need to know about sqlite-simple: <code>open</code>, <code>query_</code>, <code>query</code>, <code>FromRow</code>, <code>ToRow</code>. Oh right, one more thing. There are the functions <code>execute</code> and <code>execute_</code> if you don’t need the result of the query. They’re useful for inserting things into the database, for example.</p>
|
||||
|
||||
Reference in New Issue
Block a user