mirror of
https://github.com/iritmaximus/haskell.git
synced 2026-10-12 19:13:39 +03:00
part 2: update for GHC 9.2.8
This commit is contained in:
+13
-13
@@ -1749,7 +1749,7 @@ word: ever</code></pre>
|
||||
<span id="cb123-5"><a href="#cb123-5" aria-hidden="true" tabindex="-1"></a> operationThatProducesTheResult var2</span></code></pre></div>
|
||||
<section id="examples" data-number="3.2.1">
|
||||
<h3 data-number="11.2.1"><span class="header-section-number">11.2.1</span> Examples</h3>
|
||||
<p>You can find useful IO operations in the standard library modules <a href="https://hackage.haskell.org/package/base-4.14.1.0/docs/Prelude.html">Prelude</a> and <a href="https://hackage.haskell.org/package/base-4.14.1.0/docs/System-IO.html">System.IO</a></p>
|
||||
<p>You can find useful IO operations in the standard library modules <a href="https://hackage.haskell.org/package/base-4.16.4.0/docs/Prelude.html">Prelude</a> and <a href="https://hackage.haskell.org/package/base-4.16.4.0/docs/System-IO.html">System.IO</a></p>
|
||||
<p>Here’s an IO operation that asks the user for a string, and prints out the length of the string.</p>
|
||||
<div class="sourceCode" id="cb124"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb124-1"><a href="#cb124-1" aria-hidden="true" tabindex="-1"></a><span class="ot">query ::</span> <span class="dt">IO</span> ()</span>
|
||||
<span id="cb124-2"><a href="#cb124-2" aria-hidden="true" tabindex="-1"></a>query <span class="ot">=</span> <span class="kw">do</span></span>
|
||||
@@ -3572,14 +3572,14 @@ None of the above
|
||||
<li><code>Data.Text</code> represents <em>a sequence of <a href="https://en.wikipedia.org/wiki/Unicode">Unicode characters</a></em>, just like <code>String</code>, only more efficient. Used when dealing with text.</li>
|
||||
<li><code>Data.ByteString</code> represents <em>a sequence of bytes</em>. Used when dealing with binary data.</li>
|
||||
</ul>
|
||||
<p>Additionally, both of these types come in <em>lazy</em> and <em>strict</em> variants. The <a href="https://hackage.haskell.org/package/text-1.2.4.1/docs/Data-Text.html">docs for <code>Data.Text</code></a> summarize the difference well:</p>
|
||||
<p>Additionally, both of these types come in <em>lazy</em> and <em>strict</em> variants. The <a href="https://hackage.haskell.org/package/text-1.2.5.0/docs/Data-Text.html">docs for <code>Data.Text</code></a> summarize the difference well:</p>
|
||||
<blockquote>
|
||||
<p>The strict <code>Text</code> type requires that an entire string fit into memory at once. The lazy <code>Text</code> type is capable of streaming strings that are larger than memory using a small memory footprint… Each module provides an almost identical API…</p>
|
||||
</blockquote>
|
||||
<p>All of these types (<code>Text</code> and <code>ByteString</code>, strict and lazy) offer <code>pack</code> and <code>unpack</code> functions for converting from and to plain <code>String</code>s. The types also come with specialized versions of familiar list functions like <code>reverse</code>, <code>take</code>, <code>map</code> and so on.</p>
|
||||
<section id="examples-with-text" data-number="6.1.1">
|
||||
<h3 data-number="14.1.1"><span class="header-section-number">14.1.1</span> Examples with <code>Text</code></h3>
|
||||
<p>Let’s go through a short GHCi session demonstrating the use of <code>Data.Text</code>. As <a href="https://hackage.haskell.org/package/text-1.2.4.1/docs/Data-Text.html">the documentation</a> says, the <code>Data.Text</code> module is designed to be imported <em>qualified</em>. We can convert a <code>String</code> into a <code>Text</code> with the function <code>T.pack</code>. Note how a value of type <code>Text</code> gets printed just like a <code>String</code>.</p>
|
||||
<p>Let’s go through a short GHCi session demonstrating the use of <code>Data.Text</code>. As <a href="https://hackage.haskell.org/package/text-1.2.5.0/docs/Data-Text.html">the documentation</a> says, the <code>Data.Text</code> module is designed to be imported <em>qualified</em>. We can convert a <code>String</code> into a <code>Text</code> with the function <code>T.pack</code>. Note how a value of type <code>Text</code> gets printed just like a <code>String</code>.</p>
|
||||
<div class="sourceCode" id="cb312"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb312-1"><a href="#cb312-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="cb312-2"><a href="#cb312-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="cb312-3"><a href="#cb312-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>
|
||||
@@ -3769,7 +3769,7 @@ None of the above
|
||||
<section id="writing-a-http-server-wai-and-warp" data-number="6.3">
|
||||
<h2 data-number="14.3"><span class="header-section-number">14.3</span> Writing a HTTP Server: WAI and Warp</h2>
|
||||
<p>Sometimes it feels like everything in the world happens over <a href="https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">HTTP</a> and <a href="https://en.wikipedia.org/wiki/Web_API">Web Apis</a>. Your web browser, your smartphone apps, <a href="https://developer.nordeaopenbanking.com/">your bank</a>, <a href="https://tools.ietf.org/html/rfc2324">your coffee pot</a>, <a href="https://support.ring.com/hc/en-us/articles/205385394-The-Protocols-and-Ports-Used-by-Ring-Devices">and even your doorbell</a>, all talk to servers using the HTTP protocol.</p>
|
||||
<p>Let’s look at how we can set up a simple HTTP server in Haskell. The standard low level components for this are called <a href="https://hackage.haskell.org/package/wai-3.2.3/docs/Network-Wai.html">WAI</a> and <a href="https://hackage.haskell.org/package/warp-3.3.14">Warp</a>. WAI, the Web Application Interface gives us a way to define how HTTP requests are handled. Warp is a simple HTTP server that runs the logic we have defined using WAI. That probably sounds a bit abstract right now, but a simple example will help.</p>
|
||||
<p>Let’s look at how we can set up a simple HTTP server in Haskell. The standard low level components for this are called <a href="https://hackage.haskell.org/package/wai-3.2.3/docs/Network-Wai.html">WAI</a> and <a href="https://hackage.haskell.org/package/warp-3.3.23">Warp</a>. WAI, the Web Application Interface gives us a way to define how HTTP requests are handled. Warp is a simple HTTP server that runs the logic we have defined using WAI. That probably sounds a bit abstract right now, but a simple example will help.</p>
|
||||
<p>The file <a href="https://github.com/moocfi/haskell-mooc/blob/master/exercises/Examples/HelloServer.hs"><code>exercises/Examples/HelloServer.hs</code></a> implements a HTTP server that always responds with “Hello World!”. You can try it out by going to the <code>exercises/Examples</code> directory and running it with <code>stack runhaskell HelloServer.hs</code>. After that you can visit <a href="http://localhost:3421" class="uri">http://localhost:3421</a> in your browser to see the response from the server.</p>
|
||||
<div class="sourceCode" id="cb324"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb324-1"><a href="#cb324-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Examples.HelloServer</span> <span class="kw">where</span></span>
|
||||
<span id="cb324-2"><a href="#cb324-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
@@ -3788,12 +3788,12 @@ None of the above
|
||||
<span id="cb324-15"><a href="#cb324-15" aria-hidden="true" tabindex="-1"></a><span class="ot">application ::</span> <span class="dt">Application</span></span>
|
||||
<span id="cb324-16"><a href="#cb324-16" aria-hidden="true" tabindex="-1"></a>application request respond <span class="ot">=</span></span>
|
||||
<span id="cb324-17"><a href="#cb324-17" aria-hidden="true" tabindex="-1"></a> respond (responseLBS status200 [] (BL.pack <span class="st">"Hello World!"</span>))</span></code></pre></div>
|
||||
<p>Let’s look at the types in this example. There’s a lot going on here. First off, <code>Application</code> is a <em>type alias</em> for a thing that implements the logic of a web server. The <a href="https://hackage.haskell.org/package/warp-3.3.14/docs/Network-Wai-Handler-Warp.html#v:run"><code>run</code> function from Warp</a> can run <code>Application</code>s:</p>
|
||||
<p>Let’s look at the types in this example. There’s a lot going on here. First off, <code>Application</code> is a <em>type alias</em> for a thing that implements the logic of a web server. The <a href="https://hackage.haskell.org/package/warp-3.3.23/docs/Network-Wai-Handler-Warp.html#v:run"><code>run</code> function from Warp</a> can run <code>Application</code>s:</p>
|
||||
<div class="sourceCode" id="cb325"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb325-1"><a href="#cb325-1" aria-hidden="true" tabindex="-1"></a><span class="ot">run ::</span> <span class="dt">Port</span> <span class="ot">-></span> <span class="dt">Application</span> <span class="ot">-></span> <span class="dt">IO</span> ()</span>
|
||||
<span id="cb325-2"><a href="#cb325-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Application</span> <span class="ot">=</span> <span class="dt">Request</span> <span class="ot">-></span> (<span class="dt">Response</span> <span class="ot">-></span> <span class="dt">IO</span> <span class="dt">ResponseReceived</span>) <span class="ot">-></span> <span class="dt">IO</span> <span class="dt">ResponseReceived</span></span></code></pre></div>
|
||||
<p>We’ll talk about what <code>Request</code> and <code>Response</code> are soon, but from this type we can see that an <code>Application</code> is an IO operation that takes as arguments a request of type <code>Request</code>, and an IO operation <code>respond :: Response -> IO ResponseReceived</code>. Arguments like <code>respond</code> are called <em>callbacks</em> in many contexts. They allow us to call back to the library who called the application. The <code>Application</code> operation has to produce the same special <code>ResponseReceived</code> type that <code>respond</code>. You can think of this type as a token proving that <code>respond</code> was called by the <code>Application</code>.</p>
|
||||
<p>That might sound intimidating: but looking at the code things are relatively simple: our <code>server</code> is an <code>Application</code> and takes two parameters: <code>request</code> and <code>respond</code>.</p>
|
||||
<p>WAI uses lots of types like <code>Port</code>, <code>Request</code>, <code>Response</code>, <code>Status</code> to represent HTTP concepts. It’s useful to look these up in the documentation when you bump into them. For example <a href="https://hackage.haskell.org/package/warp-3.3.14/docs/Network-Wai-Handler-Warp.html#t:Port"><code>Port</code> is just an alias for <code>Int</code></a>. As another example, we can see the <a href="https://hackage.haskell.org/package/wai-3.2.2.1/docs/Network-Wai.html#v:responseLBS"><code>responseLBS</code> function</a> has the type</p>
|
||||
<p>WAI uses lots of types like <code>Port</code>, <code>Request</code>, <code>Response</code>, <code>Status</code> to represent HTTP concepts. It’s useful to look these up in the documentation when you bump into them. For example <a href="https://hackage.haskell.org/package/warp-3.3.23/docs/Network-Wai-Handler-Warp.html#t:Port"><code>Port</code> is just an alias for <code>Int</code></a>. As another example, we can see the <a href="https://hackage.haskell.org/package/wai-3.2.3/docs/Network-Wai.html#v:responseLBS"><code>responseLBS</code> function</a> has the type</p>
|
||||
<div class="sourceCode" id="cb326"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb326-1"><a href="#cb326-1" aria-hidden="true" tabindex="-1"></a><span class="ot">responseLBS ::</span> <span class="dt">Status</span> <span class="ot">-></span> <span class="dt">ResponseHeaders</span> <span class="ot">-></span> <span class="dt">ByteString</span> <span class="ot">-></span> <span class="dt">Response</span></span></code></pre></div>
|
||||
<p>where <a href="https://hackage.haskell.org/package/http-types-0.12.3/docs/Network-HTTP-Types-Status.html#t:Status"><code>Status</code> is defined in <code>Network.HTTP.Types.Status</code></a>, <a href="https://hackage.haskell.org/package/http-types-0.12.3/docs/Network-HTTP-Types-Header.html#t:ResponseHeaders"><code>ResponseHeaders</code> is a type alias for <code>[Header]</code> from <code>Network.HTTP.Types.Header</code></a>, <code>ByteString</code> is a lazy <code>ByteString</code>, and the result type <a href="https://hackage.haskell.org/package/wai-3.2.3/docs/Network-Wai.html#t:Response"><code>Response</code> is defined by <code>Network.WAI</code></a>.</p>
|
||||
<p>Finally, note that we take a shortcut and use the function <code>Data.ByteString.Lazy.Char8.pack</code> to convert a <code>String</code> into a <code>ByteString</code>. This only works for ASCII text.</p>
|
||||
@@ -3814,7 +3814,7 @@ None of the above
|
||||
<p>After implementing a HTTP server we can participate in the global graph of applications talking to each other that’s called the internet. But what use is talking if we can’t remember? A real application needs to be able to <em>persist data</em> even when it is restarted. A common way to accomplish this is to use a database.</p>
|
||||
<p>There are many different kinds of databases, but arguably the most widely used simple database is <a href="https://www.sqlite.org/index.html">SQLite</a>. SQLite is a library that lets you store data in a file and process it using <a href="">SQL, the Structured Query Language</a>. With SQLite there is no need to run a separate database server a la <a href="https://www.postgresql.org/">PostgreSQL</a> or <a href="https://www.mysql.com/">MySQL</a>.</p>
|
||||
<p>In case you’re not familiar with SQL, don’t worry, you won’t need to write any queries of your own in the exercises. If you’d like to learn a bit of SQL now, there are lots of tutorials on the web. See <a href="https://www.w3schools.com/sql/">W3Schools</a>, <a href="https://sqlzoo.net/">SQL Zoo</a> or <a href="https://www.codecademy.com/learn/learn-sql">Codecademy</a>.</p>
|
||||
<p>There are many libraries for Haskell for using SQLite, but we’ll look at one called <a href="https://hackage.haskell.org/package/sqlite-simple-0.4.18.0">sqlite-simple</a> here. Let’s explore the library in GHCi for a bit.</p>
|
||||
<p>There are many libraries for Haskell for using SQLite, but we’ll look at one called <a href="https://hackage.haskell.org/package/sqlite-simple-0.4.18.2">sqlite-simple</a> here. Let’s explore the library in GHCi for a bit.</p>
|
||||
<p>All the functions live inside <code>Database.SQLite.Simple</code>. You can open a database by giving a filename to <code>open</code>, which is an IO operation that produces a <code>Connection</code>.</p>
|
||||
<div class="sourceCode" id="cb328"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb328-1"><a href="#cb328-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> <span class="kw">import</span> <span class="dt">Database.SQLite.Simple</span></span>
|
||||
<span id="cb328-2"><a href="#cb328-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Database.SQLite.Simple</span><span class="op">></span> <span class="op">:</span>t open</span>
|
||||
@@ -3841,7 +3841,7 @@ None of the above
|
||||
<span id="cb330-5"><a href="#cb330-5" aria-hidden="true" tabindex="-1"></a> prevents the constraint ‘(<span class="dt">FromRow</span> r0)’ from being solved<span class="op">.</span></span>
|
||||
<span id="cb330-6"><a href="#cb330-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">Probable</span> fix<span class="op">:</span> use a <span class="kw">type</span> annotation to specify what ‘r0’ should be<span class="op">.</span></span>
|
||||
<span id="cb330-7"><a href="#cb330-7" aria-hidden="true" tabindex="-1"></a> <span class="co">-- rest of error omitted</span></span></code></pre></div>
|
||||
<p>Before we go on, let’s have a closer look at <code>FromRow</code>. If you’ve bumped into SQL before, you know that an SQL query returns a number of <em>rows</em>, and each row consists of a number of <em>values</em> (also called <em>columns</em>). To be able to interpret the result of an SQL query into Haskell data, we need a way to interpret these values and rows. Thus sqlite-simple defines two classes, <code>FromField</code> and <code>FromRow</code>, and a bunch of instances like the following. (You can find these instances from <a href="https://hackage.haskell.org/package/sqlite-simple-0.4.18.0/docs/Database-SQLite-Simple.html#t:FromRow">the docs</a> or by asking GHCi with <code>:info FromRow</code> etc.)</p>
|
||||
<p>Before we go on, let’s have a closer look at <code>FromRow</code>. If you’ve bumped into SQL before, you know that an SQL query returns a number of <em>rows</em>, and each row consists of a number of <em>values</em> (also called <em>columns</em>). To be able to interpret the result of an SQL query into Haskell data, we need a way to interpret these values and rows. Thus sqlite-simple defines two classes, <code>FromField</code> and <code>FromRow</code>, and a bunch of instances like the following. (You can find these instances from <a href="https://hackage.haskell.org/package/sqlite-simple-0.4.18.2/docs/Database-SQLite-Simple.html#t:FromRow">the docs</a> or by asking GHCi with <code>:info FromRow</code> etc.)</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="kw">instance</span> <span class="dt">FromField</span> <span class="dt">Int</span></span>
|
||||
<span id="cb331-2"><a href="#cb331-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">FromField</span> <span class="dt">Bool</span></span>
|
||||
<span id="cb331-3"><a href="#cb331-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">FromField</span> <span class="dt">String</span></span>
|
||||
@@ -4344,7 +4344,7 @@ TODO explain `some` and `many`
|
||||
<p>There are multiple reasons for learning Applicatives, even if they do not provide any additional power over Monads. First off, as discussed in Lecture 13, the GHC standard library nowadays makes Applicative instances for all Monads compulsory. Thus a working Haskell programmer is bound to see lots of Applicative instances.</p>
|
||||
<p>Secondly, you’ll bump into Applicative operators a lot even in Monadic code. Expressions like <code>f <$> x <*> y <*> z</code> can be useful in many Monadic contexts. Also, since the <code>Traversable</code> type class is built in terms of <code>Applicative</code>, you’ll often use applicative operations with it.</p>
|
||||
<p>Thirdly, Applicatives are an excellent exercise in understanding functional design patterns. They marry the Functor pattern with the Monoid pattern, and Alternative brings in yet another Monoid-like dimension. Being able to efficiently work with Applicatives will make working with further abstractions like <em>monad transformers</em> or <em>lenses</em> easier.</p>
|
||||
<p>Lastly, there are a couple of types that are Applicatives but not Monads. <code>Validation</code> is one example, and a very practical one at that. Without understanding of Applicative, we’d have no way to recognize and generalize operations over types like this. Another such type is <a href="https://hackage.haskell.org/package/base-4.14.1.0/docs/Control-Applicative.html#t:ZipList"><code>ZipList</code></a>.</p>
|
||||
<p>Lastly, there are a couple of types that are Applicatives but not Monads. <code>Validation</code> is one example, and a very practical one at that. Without understanding of Applicative, we’d have no way to recognize and generalize operations over types like this. Another such type is <a href="https://hackage.haskell.org/package/base-4.16.4.0/docs/Control-Applicative.html#t:ZipList"><code>ZipList</code></a>.</p>
|
||||
</section>
|
||||
<section id="applicatives-in-the-wild" data-number="7.8.2">
|
||||
<h3 data-number="15.8.2"><span class="header-section-number">15.8.2</span> Applicatives in the Wild</h3>
|
||||
@@ -4573,7 +4573,7 @@ TODO explain `some` and `many`
|
||||
<span id="cb408-2"><a href="#cb408-2" aria-hidden="true" tabindex="-1"></a>propLastFixed (<span class="dt">NonEmpty</span> xs) <span class="ot">=</span> <span class="fu">last</span> xs <span class="op">===</span> <span class="fu">head</span> (<span class="fu">reverse</span> xs)</span></code></pre></div>
|
||||
<div class="sourceCode" id="cb409"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb409-1"><a href="#cb409-1" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Examples.QuickCheck</span><span class="op">></span> quickCheck propLastFixed</span>
|
||||
<span id="cb409-2"><a href="#cb409-2" aria-hidden="true" tabindex="-1"></a><span class="op">+++</span> <span class="dt">OK</span>, passed <span class="dv">100</span> tests<span class="op">.</span></span></code></pre></div>
|
||||
<p>There are <a href="https://hackage.haskell.org/package/QuickCheck-2.14.2/docs/Test-QuickCheck.html#g:16">other modifiers</a> like this, for example <code>Positive</code> for positive numbers, <code>NonNegative</code> for non-negative numbers, or <code>SortedList</code> for a sorted list. Here’s an example of a more complex test. We check that the nth element of <code>cycle xs</code> is correct. Both of the modifiers are needed, since <code>!!</code> doesn’t work with negative inputs, and <code>cycle []</code> is an error.</p>
|
||||
<p>There are <a href="https://hackage.haskell.org/package/QuickCheck-2.14.3/docs/Test-QuickCheck.html#g:16">other modifiers</a> like this, for example <code>Positive</code> for positive numbers, <code>NonNegative</code> for non-negative numbers, or <code>SortedList</code> for a sorted list. Here’s an example of a more complex test. We check that the nth element of <code>cycle xs</code> is correct. Both of the modifiers are needed, since <code>!!</code> doesn’t work with negative inputs, and <code>cycle []</code> is an error.</p>
|
||||
<div class="sourceCode" id="cb410"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb410-1"><a href="#cb410-1" aria-hidden="true" tabindex="-1"></a><span class="ot">propCycle ::</span> <span class="dt">NonEmptyList</span> <span class="dt">Int</span> <span class="ot">-></span> <span class="dt">NonNegative</span> <span class="dt">Int</span> <span class="ot">-></span> <span class="dt">Property</span></span>
|
||||
<span id="cb410-2"><a href="#cb410-2" aria-hidden="true" tabindex="-1"></a>propCycle (<span class="dt">NonEmpty</span> xs) (<span class="dt">NonNegative</span> n) <span class="ot">=</span></span>
|
||||
<span id="cb410-3"><a href="#cb410-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">cycle</span> xs <span class="op">!!</span> n <span class="op">===</span> xs <span class="op">!!</span> (<span class="fu">mod</span> n (<span class="fu">length</span> xs))</span></code></pre></div>
|
||||
@@ -4797,7 +4797,7 @@ TODO explain `some` and `many`
|
||||
<span id="cb442-3"><a href="#cb442-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> <span class="fu">map</span> fib [<span class="dv">29</span>,<span class="dv">29</span>,<span class="dv">29</span>,<span class="dv">29</span>,<span class="dv">29</span>]</span>
|
||||
<span id="cb442-4"><a href="#cb442-4" aria-hidden="true" tabindex="-1"></a>[<span class="dv">832040</span>,<span class="dv">832040</span>,<span class="dv">832040</span>,<span class="dv">832040</span>,<span class="dv">832040</span>]</span>
|
||||
<span id="cb442-5"><a href="#cb442-5" aria-hidden="true" tabindex="-1"></a>(<span class="fl">7.54</span> secs, <span class="dv">2</span>,<span class="dv">440</span>,<span class="dv">860</span>,<span class="dv">632</span> bytes)</span></code></pre></div>
|
||||
<p>Now let’s bring in the module <a href="https://hackage.haskell.org/package/parallel-3.2.1.1/docs/Control-Parallel-Strategies.html">Control.Parallel.Strategies</a> that defines ways to evaluate values in parallel. We’ll use the <code>parList rseq</code> strategy to evaluate all the elements of the list to WHNF, <em>in parallel</em>.</p>
|
||||
<p>Now let’s bring in the module <a href="https://hackage.haskell.org/package/parallel-3.2.2.0/docs/Control-Parallel-Strategies.html">Control.Parallel.Strategies</a> that defines ways to evaluate values in parallel. We’ll use the <code>parList rseq</code> strategy to evaluate all the elements of the list to WHNF, <em>in parallel</em>.</p>
|
||||
<div class="sourceCode" id="cb443"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb443-1"><a href="#cb443-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">></span> <span class="kw">import</span> <span class="dt">Control.Parallel.Strategies</span></span>
|
||||
<span id="cb443-2"><a href="#cb443-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span> <span class="dt">Control.Parallel.Strategies</span><span class="op">></span> withStrategy (parList rseq) (<span class="fu">map</span> fib [<span class="dv">29</span>,<span class="dv">29</span>,<span class="dv">29</span>,<span class="dv">29</span>,<span class="dv">29</span>])</span>
|
||||
<span id="cb443-3"><a href="#cb443-3" aria-hidden="true" tabindex="-1"></a>[<span class="dv">832040</span>,<span class="dv">832040</span>,<span class="dv">832040</span>,<span class="dv">832040</span>,<span class="dv">832040</span>]</span>
|
||||
@@ -4822,7 +4822,7 @@ TODO explain `some` and `many`
|
||||
<pre><code>Prelude Control.Concurrent> concurrency
|
||||
AABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABB</code></pre>
|
||||
<p>The operation <code>forkIO :: IO () -> IO ThreadId</code> takes an IO operation and starts running it in the backgroud. It produces a <code>ThreadId</code> that can be used to e.g. terminate the thread.</p>
|
||||
<p>If we want to add actual communication between threads, we can use abstractions like <a href="https://hackage.haskell.org/package/base-4.14.1.0/docs/Control-Concurrent-MVar.html"><code>MVar</code></a> (a mutable thread-safe variable) or <a href="https://hackage.haskell.org/package/base-4.14.1.0/docs/Control-Concurrent-Chan.html"><code>Chan</code></a> (a queue).</p>
|
||||
<p>If we want to add actual communication between threads, we can use abstractions like <a href="https://hackage.haskell.org/package/base-4.16.4.0/docs/Control-Concurrent-MVar.html"><code>MVar</code></a> (a mutable thread-safe variable) or <a href="https://hackage.haskell.org/package/base-4.16.4.0/docs/Control-Concurrent-Chan.html"><code>Chan</code></a> (a queue).</p>
|
||||
<p>Here’s a simple example where one thread writes a value to an <code>MVar</code> and another one waits for them and prints them. An <code>MVar</code> works like a mailbox: it is either empty or full. Calling <code>takeMVar</code> on an empty box waits for the box to get filled (with a <code>putMVar</code>). Symmetrically, trying to <code>putMVar</code> into a full box waits until the box is empty.</p>
|
||||
<div class="sourceCode" id="cb446"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb446-1"><a href="#cb446-1" aria-hidden="true" tabindex="-1"></a><span class="ot">takeMVar ::</span> <span class="dt">MVar</span> a <span class="ot">-></span> <span class="dt">IO</span> a</span>
|
||||
<span id="cb446-2"><a href="#cb446-2" aria-hidden="true" tabindex="-1"></a><span class="ot">putMVar ::</span> <span class="dt">MVar</span> a <span class="ot">-></span> a <span class="ot">-></span> <span class="dt">IO</span> ()</span>
|
||||
@@ -4882,7 +4882,7 @@ AABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABB
|
||||
<ul>
|
||||
<li>Monad transformers: <a href="https://book.realworldhaskell.org/read/monad-transformers.html">RWH</a>, <a href="https://en.wikibooks.org/wiki/Haskell/Monad_transformers">Wikibook</a></li>
|
||||
<li>Free monads (advanced topic): <a href="https://www.haskellforall.com/2012/06/you-could-have-invented-free-monads.html">blog</a></li>
|
||||
<li>Lenses (advanced topic): <a href="https://hackage.haskell.org/package/lens-tutorial-1.0.3/docs/Control-Lens-Tutorial.html">tutorial</a> <a href="https://oleg.fi/gists/posts/2017-04-18-glassery.html">glassery</a></li>
|
||||
<li>Lenses (advanced topic): <a href="https://hackage.haskell.org/package/lens-tutorial-1.0.4/docs/Control-Lens-Tutorial.html">tutorial</a> <a href="https://oleg.fi/gists/posts/2017-04-18-glassery.html">glassery</a></li>
|
||||
<li><a href="https://bartoszmilewski.com/">Bartosz Milewski</a> covers lots of intermediate and advanced topics on his blog</li>
|
||||
</ul></li>
|
||||
<li>Tooling
|
||||
|
||||
Reference in New Issue
Block a user