mirror of
https://github.com/iritmaximus/haskell.git
synced 2026-10-12 19:13:39 +03:00
@@ -4,4 +4,4 @@ haskell-mooc is licensed under a
|
|||||||
Creative Commons Attribution-ShareAlike 4.0 International License.
|
Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
|
||||||
You should have received a copy of the license along with this
|
You should have received a copy of the license along with this
|
||||||
work. If not, see <http://creativecommons.org/licenses/by-sa/4.0/>.
|
work. If not, see <https://creativecommons.org/licenses/by-sa/4.0/>.
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ University of Helsinki
|
|||||||
|
|
||||||
[Course page](https://haskell.mooc.fi)
|
[Course page](https://haskell.mooc.fi)
|
||||||
|
|
||||||
[](http://creativecommonse.org/licenses/by-sa/4.0/)
|
[](https://creativecommons.org/licenses/by-sa/4.0/)
|
||||||
|
|
||||||
This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).
|
This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/).
|
||||||
|
|
||||||
_New!_ Exercise repository updated to use GHC 9.2.8! You'll need to rerun `stack build`.
|
_New!_ Exercise repository updated to use GHC 9.2.8! You'll need to rerun `stack build`.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4086,7 +4086,7 @@ If I define an instance for <code>Num</code>, I also get an instance for <code>F
|
|||||||
<p><a href="https://haskell.mooc.fi/part2">Part 2 of the course</a> is now out! Part 2 will cover topics like Monads, IO and how Haskell works under the hood. We’ll also get to do some real world programming with networks and databases. Oh and testing in Haskell is also covered.</p>
|
<p><a href="https://haskell.mooc.fi/part2">Part 2 of the course</a> is now out! Part 2 will cover topics like Monads, IO and how Haskell works under the hood. We’ll also get to do some real world programming with networks and databases. Oh and testing in Haskell is also covered.</p>
|
||||||
<p>If you don’t feel like jumping into part 2 right now, here are some other Haskell resources you should be able to follow now:</p>
|
<p>If you don’t feel like jumping into part 2 right now, here are some other Haskell resources you should be able to follow now:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="http://book.realworldhaskell.org/read/">Real World Haskell</a> - free e-book on advanced topics</li>
|
<li><a href="https://book.realworldhaskell.org/read/">Real World Haskell</a> - free e-book on advanced topics</li>
|
||||||
<li><a href="https://web.archive.org/web/20220513191346/http://dev.stephendiehl.com/hask/">What I Wish I Knew When Learning Haskell</a></li>
|
<li><a href="https://web.archive.org/web/20220513191346/http://dev.stephendiehl.com/hask/">What I Wish I Knew When Learning Haskell</a></li>
|
||||||
<li><a href="https://en.wikibooks.org/wiki/Haskell">The Haskell Wikibook</a></li>
|
<li><a href="https://en.wikibooks.org/wiki/Haskell">The Haskell Wikibook</a></li>
|
||||||
<li><a href="https://www.haskell.org/">The Haskell Website</a> has links to talks and presentations</li>
|
<li><a href="https://www.haskell.org/">The Haskell Website</a> has links to talks and presentations</li>
|
||||||
|
|||||||
+8
-8
@@ -1372,7 +1372,7 @@ square ==> * ==> * ==> 16
|
|||||||
<span id="cb94-12"><a href="#cb94-12" aria-hidden="true" tabindex="-1"></a><span class="op">==></span> <span class="fu">seq</span> <span class="dv">6</span> (foldl' (<span class="op">+</span>) <span class="dv">6</span> [])</span>
|
<span id="cb94-12"><a href="#cb94-12" aria-hidden="true" tabindex="-1"></a><span class="op">==></span> <span class="fu">seq</span> <span class="dv">6</span> (foldl' (<span class="op">+</span>) <span class="dv">6</span> [])</span>
|
||||||
<span id="cb94-13"><a href="#cb94-13" aria-hidden="true" tabindex="-1"></a><span class="op">==></span> foldl' (<span class="op">+</span>) <span class="dv">6</span> []</span>
|
<span id="cb94-13"><a href="#cb94-13" aria-hidden="true" tabindex="-1"></a><span class="op">==></span> foldl' (<span class="op">+</span>) <span class="dv">6</span> []</span>
|
||||||
<span id="cb94-14"><a href="#cb94-14" aria-hidden="true" tabindex="-1"></a><span class="op">==></span> <span class="dv">6</span></span></code></pre></div>
|
<span id="cb94-14"><a href="#cb94-14" aria-hidden="true" tabindex="-1"></a><span class="op">==></span> <span class="dv">6</span></span></code></pre></div>
|
||||||
<p>We won’t dive deeper into this subject on this course, but it’s important that you’re aware that <code>seq</code> exists. You can find more about <code>seq</code> on <a href="https://wiki.haskell.org/Seq">the Haskell Wiki</a> and learn more about when it is necessary to add strictness in <a href="https://book.realworldhaskell.org/read/profiling-and-optimization.html">Real World Haskell</a>. Often it’s nicer to use <em>bang patterns</em> instead of <code>seq</code>, as discussed by <a href="https://www.fpcomplete.com/blog/2017/09/all-about-strictness/">FPComplete</a> and <a href="http://book.realworldhaskell.org/read/profiling-and-optimization.html">Real World Haskell</a>.</p>
|
<p>We won’t dive deeper into this subject on this course, but it’s important that you’re aware that <code>seq</code> exists. You can find more about <code>seq</code> on <a href="https://wiki.haskell.org/Seq">the Haskell Wiki</a> and learn more about when it is necessary to add strictness in <a href="https://book.realworldhaskell.org/read/profiling-and-optimization.html">Real World Haskell</a>. Often it’s nicer to use <em>bang patterns</em> instead of <code>seq</code>, as discussed by <a href="https://www.fpcomplete.com/blog/2017/09/all-about-strictness/">FPComplete</a> and <a href="https://book.realworldhaskell.org/read/profiling-and-optimization.html">Real World Haskell</a>.</p>
|
||||||
</section>
|
</section>
|
||||||
<section id="newtype-declarations" data-number="2.7">
|
<section id="newtype-declarations" data-number="2.7">
|
||||||
<h2 data-number="10.7"><span class="header-section-number">10.7</span> Newtype Declarations</h2>
|
<h2 data-number="10.7"><span class="header-section-number">10.7</span> Newtype Declarations</h2>
|
||||||
@@ -3769,7 +3769,7 @@ None of the above
|
|||||||
<section id="writing-a-http-server-wai-and-warp" data-number="6.3">
|
<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>
|
<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>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="http://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.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>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>
|
<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>
|
<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>
|
<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-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-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>
|
<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="http://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.14/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>
|
<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>
|
<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>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>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="http://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.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>
|
||||||
<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>
|
<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>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>
|
<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>
|
||||||
@@ -4880,20 +4880,20 @@ AABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABB
|
|||||||
</ul></li>
|
</ul></li>
|
||||||
<li>Abstractions
|
<li>Abstractions
|
||||||
<ul>
|
<ul>
|
||||||
<li>Monad transformers: <a href="http://book.realworldhaskell.org/read/monad-transformers.html">RWH</a>, <a href="https://en.wikibooks.org/wiki/Haskell/Monad_transformers">Wikibook</a></li>
|
<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>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="http://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.3/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>
|
<li><a href="https://bartoszmilewski.com/">Bartosz Milewski</a> covers lots of intermediate and advanced topics on his blog</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
<li>Tooling
|
<li>Tooling
|
||||||
<ul>
|
<ul>
|
||||||
<li>Using <a href="https://www.haskell.org/cabal/">Cabal</a> and <a href="https://www.haskellstack.org">Stack</a> to build your own projects</li>
|
<li>Using <a href="https://www.haskell.org/cabal/">Cabal</a> and <a href="https://www.haskellstack.org">Stack</a> to build your own projects</li>
|
||||||
<li>Profiling: <a href="http://book.realworldhaskell.org/read/profiling-and-optimization.html">RWH</a>, <a href="https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html">GHC</a></li>
|
<li>Profiling: <a href="https://book.realworldhaskell.org/read/profiling-and-optimization.html">RWH</a>, <a href="https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html">GHC</a></li>
|
||||||
<li><a href="https://github.com/ndmitchell/hlint#readme">Hlint</a></li>
|
<li><a href="https://github.com/ndmitchell/hlint#readme">Hlint</a></li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
<li>Libraries
|
<li>Libraries
|
||||||
<ul>
|
<ul>
|
||||||
<li>Parsec (parsing): <a href="http://book.realworldhaskell.org/read/using-parsec.html">RWH</a></li>
|
<li>Parsec (parsing): <a href="https://book.realworldhaskell.org/read/using-parsec.html">RWH</a></li>
|
||||||
<li>Scotty (simple web framework), Aeson (json): <a href="https://seanhess.github.io/2015/08/19/practical-haskell-json-api.html">blog</a></li>
|
<li>Scotty (simple web framework), Aeson (json): <a href="https://seanhess.github.io/2015/08/19/practical-haskell-json-api.html">blog</a></li>
|
||||||
<li><a href="https://haskell-servant.github.io/">Servant</a> (fancy web framework with phantom types)</li>
|
<li><a href="https://haskell-servant.github.io/">Servant</a> (fancy web framework with phantom types)</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
|
|||||||
Reference in New Issue
Block a user