<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Monadfix Library</title><id>https://monadfix.com#library</id><updated>2019-02-03T00:00:00Z</updated><link href="https://monadfix.com#library"/><entry><id>2018-10-15-servant-mocking</id><title type="html">Network-less mocking with Servant
</title><updated>2019-02-03T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-10-15-servant-mocking&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random3.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I have an HTTP service which, from the point of view of my code, I see
only as a Servant client.&lt;/p&gt;
&lt;p&gt;[...] Now I want to mock out the service, i.e. I want to implement
another interpreter for my HTTP effect, which – instead of making a call
to a distant service – will return whatever strikes my fancy. Generally
I am willing to change large parts of my architecture, as all three
solutions I have come up with are horrible.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;One is to parse the &lt;code style=&#34;white-space: nowrap&#34;&gt;Request&lt;/code&gt; and do routing myself, which is
error-prone and stupid. I should be able to use Servant for this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The other one is to spin up a Servant server and make it do the
routing. The problem with this is that in my property tests, when I
try to spin a new server for every function call, there is some issue
with resource acquisition by kernel or &lt;code&gt;Network.Wai&lt;/code&gt; and we run out
of ports and everything dies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Or I could write a lot of boilerplate code and define another effect
which would represent an RPC call. Then basically almost copy and
paste this GADT, make it a Servant type, and have two RPC effects
interpreters (one doing HTTP calls and another returning my mocked
stuff). I dislike this copy and paste bit.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Any hints?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note 2019-02-03:&lt;/strong&gt; there is similar functionality implemented in
&lt;a href=&#34;http://hackage.haskell.org/package/wai-extra-3.0.25/docs/Network-Wai-Test.html&#34;&gt;&lt;code&gt;Network.Wai.Test&lt;/code&gt;&lt;/a&gt;, but it doesn&amp;#39;t integrate with Servant so
nicely. Understanding the internals of network-related libraries is
also particularly useful, because then you can hack various nice
features into them. For some unclear reason it comes up with
network-related and web-related libraries more often than with other
kinds of libraries.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;networkless-requests&#34;&gt;Network-less requests&lt;/h2&gt;
&lt;p&gt;You should be able to do requests without ever making any networking.
&lt;code&gt;servant-server&lt;/code&gt; gives you a WAI &lt;a href=&#34;https://hackage.haskell.org/package/wai-3.2.2/docs/Network-Wai.html#t:Application&#34;&gt;&lt;code&gt;Application&lt;/code&gt;&lt;/a&gt;, which looks like
this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Application&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Request&lt;/span&gt;
&lt;span&gt;                &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseReceived&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;                &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseReceived&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A server (likely &lt;a href=&#34;https://hackage.haskell.org/package/warp&#34;&gt;warp&lt;/a&gt;) feeds our &lt;code&gt;Application&lt;/code&gt; requests and provides
a way to send back whatever responses the &lt;code&gt;Application&lt;/code&gt; wants. However,
you can create your mock server with &lt;code style=&#34;white-space: nowrap&#34;&gt;serve&lt;/code&gt; and then just feed requests
to it without starting it up.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s how it can work. &lt;code&gt;servant-client&lt;/code&gt;&amp;#39;s functions can run in anything
that implements &lt;a href=&#34;https://hackage.haskell.org/package/servant-client-core-0.15/docs/Servant-Client-Core.html#t:RunClient&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;RunClient&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Monad&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RunClient&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;    runRequest ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Request&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;    throwServantError ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ServantError&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; m a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, our &lt;code style=&#34;white-space: nowrap&#34;&gt;m&lt;/code&gt; has to have access to an &lt;code&gt;Application&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ClientMock&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ReaderT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Application&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A slight problem here is that &lt;code style=&#34;white-space: nowrap&#34;&gt;Request&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Response&lt;/code&gt; come from
Servant, and they can&amp;#39;t be passed to &lt;code&gt;Application&lt;/code&gt; verbatim. If we
manage to convert between them and WAI&amp;#39;s &lt;code style=&#34;white-space: nowrap&#34;&gt;Request&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Response&lt;/code&gt;, we
have achieved our goal: we can generate client functions for a
Servant-defined API, combine them into &lt;code style=&#34;white-space: nowrap&#34;&gt;RunClient&lt;/code&gt;-polymorphic actions,
and run then either against a server or against a mock-&lt;code style=&#34;white-space: nowrap&#34;&gt;Server&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;main ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; ()&lt;/span&gt;
&lt;span&gt;main &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- We can run &amp;#39;action&amp;#39; in &amp;#39;ClientM&amp;#39; and talk to a server over the network.&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;putStrLn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;Network calls:&amp;quot;&lt;/span&gt;
&lt;span&gt;    forkIO &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; run &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;25000&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; serve (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Proxy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Api&lt;/span&gt;&lt;span&gt;) mockServer&lt;/span&gt;
&lt;span&gt;    manager &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; newManager defaultManagerSettings&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;let&lt;/span&gt;&lt;span&gt; env &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; mkClientEnv manager (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;BaseUrl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Http&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;0.0.0.0&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;25000&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;    runClientM action env&lt;/span&gt;

&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- Or we run &amp;#39;action&amp;#39; in &amp;#39;ClientMock&amp;#39; against the mock server directly!&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;putStrLn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;No network calls:&amp;quot;&lt;/span&gt;
&lt;span&gt;    runReaderT action (serve (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Proxy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Api&lt;/span&gt;&lt;span&gt;) mockServer)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;translating-requests&#34;&gt;Translating requests&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s look at Servant&amp;#39;s &lt;code style=&#34;white-space: nowrap&#34;&gt;Request&lt;/code&gt; versus WAI&amp;#39;s &lt;code style=&#34;white-space: nowrap&#34;&gt;Request&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Servant:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RequestF&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Request&lt;/span&gt;
&lt;span&gt;    {&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestPath        ::&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestQueryString ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Seq&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;QueryItem&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestBody        ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RequestBody&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;MediaType&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestAccept      ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Seq&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;MediaType&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestHeaders     ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Seq&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Header&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestHttpVersion ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;HttpVersion&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestMethod      ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Method&lt;/span&gt;
&lt;span&gt;    }&lt;/span&gt;
&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Request&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RequestF&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Builder&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- Data.ByteString.Builder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;WAI:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Request&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Request&lt;/span&gt;
&lt;span&gt;    {&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestMethod          ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Method&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; httpVersion            ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;HttpVersion&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; rawPathInfo            ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ByteString&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; rawQueryString         ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ByteString&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestHeaders         ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RequestHeaders&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; isSecure               ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bool&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; remoteHost             ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;SockAddr&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; pathInfo               ::&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Text&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; queryString            ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Query&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestBody            ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ByteString&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; vault                  ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Vault&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestBodyLength      ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RequestBodyLength&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestHeaderHost      ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ByteString&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestHeaderRange     ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ByteString&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestHeaderReferer   ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ByteString&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; requestHeaderUserAgent ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ByteString&lt;/span&gt;
&lt;span&gt;    }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Servant&amp;#39;s type is quite a bit more high-level than we&amp;#39;d like. Luckily
&lt;code&gt;servant-client&lt;/code&gt; provides a function (somewhere in its internals) to
convert that type into &lt;code&gt;http-client&lt;/code&gt;&amp;#39;s request type, and that one is
easier to deal with. In fact, the translation becomes boring enough that
I will link to it instead of including it here: &lt;a href=&#34;https://github.com/monadfix/examples/blob/f5d6d2fdacdcff9641076a5cd9cbf4d596fbeb61/servant-mock/src/Mock.hs#L80-L121&#34;&gt;&lt;code&gt;toWaiRequest&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;translating-responses&#34;&gt;Translating responses&lt;/h2&gt;
&lt;p&gt;There are four kinds of responses the &lt;code&gt;Application&lt;/code&gt; can give us:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseFile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Status&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseHeaders&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FilePath&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FilePart&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseBuilder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Status&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseHeaders&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Builder&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseStream&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Status&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseHeaders&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;StreamingBody&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseRaw&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ByteString&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ByteString&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; ()) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; ()) &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For simplicity I will only handle &lt;code&gt;ResponseBuilder&lt;/code&gt; as the most common
one (and the only one &lt;code&gt;servant-server&lt;/code&gt; uses unless you enable
streaming, as can be checked via &lt;a href=&#34;https://codesearch.aelve.com/haskell/search?query=response(file%7clbs%7cstream%7cbuilder%7craw)&amp;amp;filePath=servant-server&amp;amp;insensitive=on&amp;amp;space=off&amp;amp;precise=off&amp;amp;sources=on&#34;&gt;Codesearch&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Servant&amp;#39;s response type is, on the other hand, rather pleasant:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;GenResponse&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;
&lt;span&gt;    {&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; responseStatusCode  ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Status&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; responseHeaders     ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Seq.Seq&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Header&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; responseHttpVersion ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;HttpVersion&lt;/span&gt;
&lt;span&gt;    ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; responseBody        ::&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;    }&lt;/span&gt;
&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;GenResponse&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LBS.ByteString&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This time the implementation is short enough that I will provide it in
text:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;fromWaiResponse ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Wai.Response&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;
&lt;span&gt;fromWaiResponse (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Wai.ResponseBuilder&lt;/span&gt;&lt;span&gt; status headers builder) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;pure&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;
&lt;span&gt;        { responseStatusCode &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; status&lt;/span&gt;
&lt;span&gt;        , responseHeaders &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; fromList headers&lt;/span&gt;
&lt;span&gt;        , responseHttpVersion &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; HTTP.http11  &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- always HTTP/1.1 for servant-client&lt;/span&gt;
&lt;span&gt;        , responseBody &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; Builder.toLazyByteString builder&lt;/span&gt;
&lt;span&gt;        }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;putting-it-all-together&#34;&gt;Putting it all together&lt;/h2&gt;
&lt;p&gt;We still need our &lt;code style=&#34;white-space: nowrap&#34;&gt;RunClient&lt;/code&gt; instance, and it&amp;#39;s not exactly trivial. We
need to get back the &lt;code style=&#34;white-space: nowrap&#34;&gt;Response&lt;/code&gt;, but the &lt;code&gt;Application&lt;/code&gt; doesn&amp;#39;t let us
return anything:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Application&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Request&lt;/span&gt;
&lt;span&gt;                &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseReceived&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;                &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ResponseReceived&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can solve this problem by sneakily putting the &lt;code style=&#34;white-space: nowrap&#34;&gt;Response&lt;/code&gt; into an
&lt;code style=&#34;white-space: nowrap&#34;&gt;MVar&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RunClient&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ClientMock&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;    runRequest ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Request&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ClientMock&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;
&lt;span&gt;    runRequest request &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ReaderT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; \app &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;        responseMVar &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; newEmptyMVar &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Response&lt;/span&gt;
&lt;span&gt;        &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; storeResponse ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Wai.Response&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Wai.ResponseReceived&lt;/span&gt;
&lt;span&gt;            storeResponse waiResponse &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;                response &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; fromWaiResponse waiResponse&lt;/span&gt;
&lt;span&gt;                putMVar responseMVar response&lt;/span&gt;
&lt;span&gt;                &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;pure&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Wai.ResponseReceived&lt;/span&gt;
&lt;span&gt;        &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Wai.ResponseReceived&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; app (toWaiRequest request) storeResponse&lt;/span&gt;
&lt;span&gt;        takeMVar responseMVar&lt;/span&gt;

&lt;span class=&#34;ot&#34;&gt;    throwServantError ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ServantError&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ClientMock&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;    throwServantError &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; lift &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.&lt;/span&gt;&lt;span&gt; throwIO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(It&amp;#39;s a bit tricky to understand why it looks like this instead of
simpler &lt;code&gt;Request -&amp;gt; IO Response&lt;/code&gt;; reading a &lt;a href=&#34;https://www.reddit.com/r/haskell/comments/4vu9ju/why_does_wai_use_cps/&#34;&gt;Reddit thread&lt;/a&gt; on this
topic might help. The short explanation is that if the &lt;code&gt;Application&lt;/code&gt;
needs to open a resource in order to answer a request, it should also
make sure to close the resource after the response has been sent, even
if the sending operation fails. Thus the sending has to be done inside
whatever &lt;code style=&#34;white-space: nowrap&#34;&gt;bracket&lt;/code&gt;-ing the &lt;code&gt;Application&lt;/code&gt; does.)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note 2019-02-03:&lt;/strong&gt; this code, together with a usage example, lives
at &lt;a href=&#34;https://github.com/monadfix/examples/tree/master/servant-mock&#34;&gt;monadfix/examples&lt;/a&gt;. It has not yet been packaged into a library,
partly because it doesn&amp;#39;t yet work with streaming and doesn&amp;#39;t remember
cookies between requests. If you end up using it, feel free to &lt;a href=&#34;mailto:hi@monadfix.com&#34;&gt;drop a
line&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-10-15-servant-mocking"/></entry><entry><id>2018-10-23-stop-profiling</id><title type="html">Stopping profiling from inside the app
</title><updated>2019-02-03T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-10-23-stop-profiling&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random2.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Our app has a big cost during startup that I&amp;#39;d like to
ignore in the &lt;code style=&#34;white-space: nowrap&#34;&gt;.prof&lt;/code&gt; output. Is there a way to send a
signal to the process to tell it to forget all its profiling
information to date?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;&lt;code&gt;stopProfTimer&lt;/code&gt; and &lt;code&gt;startProfTimer&lt;/code&gt; in &lt;a href=&#34;http://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-Profiling.html&#34;&gt;&lt;code&gt;GHC.Profiling&lt;/code&gt;&lt;/a&gt;
might work. Allocation info will still be collected, but timing
info (ticks) will not.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-10-23-stop-profiling"/></entry><entry><id>2018-11-02-aeson-and-keywords</id><title type="html">Using Aeson with field names like &lt;code style=&#34;white-space: nowrap&#34;&gt;&amp;quot;data&amp;quot;&lt;/code&gt;
</title><updated>2019-02-03T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-11-02-aeson-and-keywords&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random2.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;We have a data type that needs an Aeson encoder / decoder, but one of
the field names in the JSON payload is &lt;code style=&#34;white-space: nowrap&#34;&gt;&amp;quot;data&amp;quot;&lt;/code&gt;, which is a reserved
keyword. How can we specify a custom field name? (Without writing a
custom manual instance.)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Just name your field &lt;code style=&#34;white-space: nowrap&#34;&gt;data_&lt;/code&gt; and then use custom Aeson options:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ToJSON&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Foo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;    toJSON &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; genericToJSON defaultOptions&lt;/span&gt;
&lt;span&gt;        { fieldLabelModifier &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; unmangle }&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FromJSON&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Person&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;    parseJSON &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; genericParseJSON defaultOptions&lt;/span&gt;
&lt;span&gt;        { fieldLabelModifier &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; unmangle }&lt;/span&gt;

&lt;span class=&#34;ot&#34;&gt;unmangle ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;String&lt;/span&gt;
&lt;span&gt;unmangle &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;data_&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;data&amp;quot;&lt;/span&gt;
&lt;span&gt;unmangle &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;type_&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;
&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;unmangle x &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-11-02-aeson-and-keywords"/></entry><entry><id>2019-01-02-rank-2-functor</id><title type="html">Is this typeclass for rank-2 functors defined anywhere?
</title><updated>2019-02-03T00:00:00Z</updated><content type="html">&lt;div id=&#34;2019-01-02-rank-2-functor&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random2.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I just sketched out a typeclass sig that roughly matches what I&amp;#39;m looking for... Anybody recognise this?&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ZFunctor&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;m ::&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;    zoist ::&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;forall&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.&lt;/span&gt;&lt;span&gt; b a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; c a) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; m b &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; m c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&amp;#39;s not &lt;code style=&#34;white-space: nowrap&#34;&gt;Functor&lt;/code&gt;, &lt;code style=&#34;white-space: nowrap&#34;&gt;HFunctor&lt;/code&gt;, &lt;code style=&#34;white-space: nowrap&#34;&gt;MFunctor&lt;/code&gt; or &lt;code style=&#34;white-space: nowrap&#34;&gt;MonadTrans&lt;/code&gt;, but it&amp;#39;s very close. The usecase is that if you have some &lt;code&gt;data Foo m = Foo { doStuff :: m String }&lt;/code&gt; dictionary of functions, if there was a &lt;code&gt;ZFunctor Foo&lt;/code&gt; then you could &lt;code style=&#34;white-space: nowrap&#34;&gt;zoist&lt;/code&gt; a &lt;code style=&#34;white-space: nowrap&#34;&gt;Foo m&lt;/code&gt; into any &lt;code style=&#34;white-space: nowrap&#34;&gt;Foo n&lt;/code&gt; if there is an &lt;code style=&#34;white-space: nowrap&#34;&gt;m ~&amp;gt; n&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Even this would be useful:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IFunctor&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;m ::&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;    ioist ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;MonadIO&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; m n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Indeed it&amp;#39;s a functor, but it&amp;#39;s not an endofunctor. You won&amp;#39;t find a class for every sort of functor out there. There&amp;#39;s &lt;a href=&#34;http://hackage.haskell.org/package/categories-1.0.7/docs/Control-Categorical-Functor.html&#34;&gt;&lt;code&gt;Control.Categorical.Functor&lt;/code&gt;&lt;/a&gt; that covers most of them, &lt;code&gt;type IFunctor f = Categorical.Functor f (:~&amp;gt;) (-&amp;gt;)&lt;/code&gt; as far as I can tell.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/effectfully&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/effectfully.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Roman Kireev&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Additionally, the first class you&amp;#39;re asking about is used in two contexts: the &lt;a href=&#34;http://reasonablypolymorphic.com/blog/higher-kinded-data&#34;&gt;higher-kinded data pattern&lt;/a&gt; which seems to be your exact use case, and in the more general context of rank-2 classes (there is also &lt;code&gt;Traversable&lt;/code&gt;, &lt;code&gt;Distributive&lt;/code&gt; etc): &lt;a href=&#34;http://hackage.haskell.org/package/rank2classes-1.2/docs/Rank2.html&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;Rank2&lt;/code&gt;&lt;/a&gt;. The latter library also allows to derive instances via Template Haskell. &lt;code style=&#34;white-space: nowrap&#34;&gt;ZFunctor&lt;/code&gt; there is called simply &lt;code style=&#34;white-space: nowrap&#34;&gt;Functor&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2019-01-02-rank-2-functor"/></entry><entry><id>2018-09-17-servant-client-request</id><title type="html">Debugging requests done by &lt;code&gt;servant-client&lt;/code&gt;
</title><updated>2019-02-02T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-09-17-servant-client-request&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random1.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I have some &lt;code&gt;servant-client&lt;/code&gt; code that is giving me a 404. How do I get
the URL it thinks it is hitting?&lt;/p&gt;
&lt;p&gt;The error type itself doesn&amp;#39;t include that info, and due to the wonders
of Servant&amp;#39;s auto-generation of everything I&amp;#39;m never constructing a URL
I can manually print.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;You can render the whole routing tree by using the &lt;a href=&#34;https://hackage.haskell.org/package/servant-server-0.14.1/docs/Servant-Server.html#v:layout&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;layout&lt;/code&gt;&lt;/a&gt;
function.&lt;/p&gt;
&lt;p&gt;There&amp;#39;s also an implementation via &lt;code style=&#34;white-space: nowrap&#34;&gt;Free&lt;/code&gt; that lets you look at the
request: see &lt;a href=&#34;https://hackage.haskell.org/package/servant-client-core-0.14.1/docs/Servant-Client-Free.html&#34;&gt;&lt;code&gt;Servant.Client.Free&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://haskell-servant.readthedocs.io/en/latest/cookbook/using-free-client/UsingFreeClient.html&#34;&gt;Servant
cookbook entry on the topic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course, you can also just hit a web server on localhost and see the
request.&lt;/p&gt;
&lt;p&gt;Yet another option is modifying the &lt;code style=&#34;white-space: nowrap&#34;&gt;Manager&lt;/code&gt; to print all requests
(probably the simplest one if you control the &lt;code style=&#34;white-space: nowrap&#34;&gt;Manager&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;newManager defaultManagerSettings&lt;/span&gt;
&lt;span&gt;    { managerModifyResponse &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; \resp &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;print&lt;/span&gt;&lt;span&gt; resp &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&amp;gt;&lt;/span&gt;&lt;span&gt; resp }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-09-17-servant-client-request"/></entry><entry><id>2018-03-14-generics-read</id><title type="html">Writing a simple &lt;code style=&#34;white-space: nowrap&#34;&gt;Read&lt;/code&gt; instance with generics
</title><updated>2018-03-14T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-03-14-generics-read&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I have a bunch of sum types, some with several dozen members, for which
I need to define &lt;code style=&#34;white-space: nowrap&#34;&gt;Read&lt;/code&gt; instances that are simply lowercase versions of
their constructors. I haven&amp;#39;t dug into generics yet, is there a quick
way to do this?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Here&amp;#39;s an example with &lt;a href=&#34;https://hackage.haskell.org/package/generics-eot&#34;&gt;&lt;code&gt;generics-eot&lt;/code&gt;&lt;/a&gt; (a library that
simplifies &lt;a href=&#34;https://hackage.haskell.org/package/base/docs/GHC-Generics.html&#34;&gt;&lt;code&gt;GHC.Generics&lt;/code&gt;&lt;/a&gt; by representing everything as &lt;code style=&#34;white-space: nowrap&#34;&gt;Either&lt;/code&gt;s
and tuples). Of course, you can also do it with “pure” &lt;code&gt;GHC.Generics&lt;/code&gt;,
but I forget its API after each time I use it :/&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s how it&amp;#39;s going to work:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;op&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Foo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Qux&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;deriving&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Show&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Generic&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;

&lt;span class=&#34;op&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; greadMaybe &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;T&lt;/span&gt;
&lt;span class=&#34;dt&#34;&gt;Just&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;p&gt;First, some extensions and imports:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE ScopedTypeVariables #-}&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE TypeApplications #-}&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE FlexibleInstances #-}&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE FlexibleContexts #-}&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE MonoLocalBinds #-}&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Generics.Eot&lt;/span&gt;
&lt;span class=&#34;kw&#34;&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Data.Char&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you have a type &lt;code&gt;data T = Foo | Bar | Qux&lt;/code&gt;, &lt;code&gt;generics-eot&lt;/code&gt; will
represent its constructors like this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Foo&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;-&amp;gt;&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Left&lt;/span&gt;&lt;span&gt; ()&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bar&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;-&amp;gt;&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Right&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Left&lt;/span&gt;&lt;span&gt; ())&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Qux&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;-&amp;gt;&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Right&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Right&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Left&lt;/span&gt;&lt;span&gt; ()))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can use that to generate a list of all possible values for a sum
type, assuming that none of the constructors have any fields:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;enumValues ::&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;HasEot&lt;/span&gt;&lt;span&gt; a, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;EnumType&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Eot&lt;/span&gt;&lt;span&gt; a)) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; [a]&lt;/span&gt;
&lt;span&gt;enumValues &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;map&lt;/span&gt;&lt;span&gt; fromEot enumEot      &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- &amp;#39;fromEot&amp;#39; converts a&lt;/span&gt;
&lt;span&gt;                                      &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- generic representation&lt;/span&gt;
&lt;span&gt;                                      &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- into a value of &amp;#39;a&amp;#39;&lt;/span&gt;

&lt;span class=&#34;co&#34;&gt;-- | A class for things with several zero-field constructors.&lt;/span&gt;
&lt;span class=&#34;kw&#34;&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;EnumType&lt;/span&gt;&lt;span&gt; eot &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- | Get all EOT-representations of constructors of the type.&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;  enumEot ::&lt;/span&gt;&lt;span&gt; [eot]&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;EnumType&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  enumEot &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;
&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;EnumType&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  enumEot &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; [()]&lt;/span&gt;
&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;EnumType&lt;/span&gt;&lt;span&gt; eot &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;EnumType&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Either&lt;/span&gt;&lt;span&gt; () eot) &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  enumEot &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Left&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;map&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Right&lt;/span&gt;&lt;span&gt; enumEot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can also get all constructor names by using &lt;a href=&#34;https://www.stackage.org/haddock/lts-11.1/generics-eot-0.2.1.2/Generics-Eot.html#v:datatype&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;datatype&lt;/code&gt;&lt;/a&gt;, which
returns information about a type passed via &lt;code style=&#34;white-space: nowrap&#34;&gt;Proxy&lt;/code&gt;. Unlike with
&lt;code&gt;GHC.Generics&lt;/code&gt;, the metadata in &lt;code&gt;generics-eot&lt;/code&gt; is separate from the
representation of the type, which often makes it easier to deal with.&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;enumNames ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;HasEot&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Proxy&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;String&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;span&gt;enumNames &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;map&lt;/span&gt;&lt;span&gt; constructorName &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.&lt;/span&gt;&lt;span&gt; constructors &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.&lt;/span&gt;&lt;span&gt; datatype&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we just need to construct a lookup table and we can write a generic
analog of &lt;code style=&#34;white-space: nowrap&#34;&gt;readMaybe&lt;/code&gt; (you can put the table into a &lt;code style=&#34;white-space: nowrap&#34;&gt;Map&lt;/code&gt; for some extra
performance):&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;greadMaybe&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;  ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;forall&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;HasEot&lt;/span&gt;&lt;span&gt; a, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;EnumType&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Eot&lt;/span&gt;&lt;span&gt; a))&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;greadMaybe &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;`lookup`&lt;/span&gt;&lt;span&gt; table)&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;    table ::&lt;/span&gt;&lt;span&gt; [(&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;String&lt;/span&gt;&lt;span&gt;, a)]&lt;/span&gt;
&lt;span&gt;    table &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;zip&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;map&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;map&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;toLower&lt;/span&gt;&lt;span&gt;) (enumNames (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Proxy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span&gt;a)))&lt;/span&gt;
&lt;span&gt;                enumValues&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By the way, &lt;code&gt;generics-eot&lt;/code&gt; is pretty fragile and I had spent like ten
minutes fighting with this error:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Couldn&amp;#39;t match type ‘GHC.Generics.Rep a’
               with ‘GHC.Generics.M1 GHC.Generics.D c0 f0’
  arising from a use of ‘datatype’
The type variables ‘c0’, ‘f0’ are ambiguous
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I recommend putting code that uses &lt;code&gt;generics-eot&lt;/code&gt; into a separate
module, enabling &lt;code style=&#34;white-space: nowrap&#34;&gt;-XMonoLocalBinds&lt;/code&gt; there, and optionally moving stuff
into top-level functions instead of &lt;code style=&#34;white-space: nowrap&#34;&gt;where&lt;/code&gt; clauses (otherwise it often
just doesn&amp;#39;t compile for some reason).&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;That looks fairly succinct. But in terms of performance my options are
either explicitly writing the pattern match for O(1) or using a
once-generated map for O(log n)?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;GHC does not optimize string pattern matches. You only get jump tables
(or binary trees) with integers and things that can be converted to
integers, e.g. &lt;code style=&#34;white-space: nowrap&#34;&gt;Char&lt;/code&gt;s. Everything else is going to be a linear
comparison. A map (or a trie) will actualy be faster than
pattern-matching, starting from certain amount of constructors.&lt;/p&gt;
&lt;p&gt;I recommend &lt;a href=&#34;https://godbolt.org&#34;&gt;godbolt.org&lt;/a&gt; for inspecting generated
assembly, they somehow match it up with Haskell source code and it&amp;#39;s
cool.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Do you have any resources for how the same would be written with
&lt;code&gt;GHC.Generics&lt;/code&gt;? Or &lt;a href=&#34;https://hackage.haskell.org/package/generics-sop&#34;&gt;&lt;code&gt;generics-sop&lt;/code&gt;&lt;/a&gt;, or whatever is the go-to
library of choice when you need to smooth some roughness with generic
programming.&lt;/p&gt;
&lt;p&gt;You don&amp;#39;t need to trouble yourself writing these, I was just wanting to
see some existing resources so I could reference them when I need to
solve a problem. I used the &lt;code style=&#34;white-space: nowrap&#34;&gt;TypeShape&lt;/code&gt; library in F# for almost all my
boilerplate needs and I imagine that something similar in Haskell exists
as well.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;The &lt;code&gt;generics-sop&lt;/code&gt; solution is going to be pretty similar to the
&lt;code&gt;generics-eot&lt;/code&gt; one, it&amp;#39;s just that instead of &lt;code style=&#34;white-space: nowrap&#34;&gt;Left&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Right&lt;/code&gt; you&amp;#39;ll
have &lt;code style=&#34;white-space: nowrap&#34;&gt;Z&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;S&lt;/code&gt;. As for existing resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Read the paper by the authors of &lt;code&gt;generics-sop&lt;/code&gt;: &lt;a href=&#34;https://www.andres-loeh.de/TrueSumsOfProducts/&#34;&gt;“True Sums of
Products”&lt;/a&gt;, 2014.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Steal code extensively from their sample packages
(&lt;a href=&#34;https://hackage.haskell.org/package/lens-sop&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;lens-sop&lt;/code&gt;&lt;/a&gt;, etc).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2018-03-24:&lt;/strong&gt; Andres Löh provided a &lt;code&gt;generics-sop&lt;/code&gt; solution
on Reddit: &lt;a href=&#34;https://gist.github.com/kosmikus/76ab73d92fce76091ff7b2401f271649&#34;&gt;https://gist.github.com/kosmikus/76ab73d92fce76091ff7b2401f271649&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-03-14-generics-read"/></entry><entry><id>2018-02-16-deplang-landscape</id><title type="html">“What&amp;#39;s your take on the dependently-typed languages landscape?”
</title><updated>2018-02-16T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-02-16-deplang-landscape&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random2.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;So I have a question: what’s your take on the dependently-typed languages landscape?&lt;/p&gt;
&lt;p&gt;The context is that we are planning to write some code using a more formal language than Haskell in order to provide stronger correction guarantees and we are not 100% settled on which language/prover to go with.&lt;/p&gt;
&lt;p&gt;I have played with Idris, and know a bit of Coq. Then there is Agda, Lean, F*...&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I have used Agda, Idris, and recently tried Coq.&lt;/p&gt;
&lt;p&gt;My impression of Agda: compiles to inefficient code, doesn&amp;#39;t have basic features like Haskell&amp;#39;s &lt;code style=&#34;white-space: nowrap&#34;&gt;deriving&lt;/code&gt;, no introspection of types (&lt;code style=&#34;white-space: nowrap&#34;&gt;Typeable&lt;/code&gt;), no parametric quantifier (they model &lt;code style=&#34;white-space: nowrap&#34;&gt;forall&lt;/code&gt; with &lt;code style=&#34;white-space: nowrap&#34;&gt;pi&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;My impression of Idris: no type classes (their “interfaces” don&amp;#39;t imply coherence), bad type inference, a horribly buggy compiler (I usually got stuck on a bug within a few hours of development, made three attempts to use Idris).&lt;/p&gt;
&lt;p&gt;Can&amp;#39;t say anything of substance about Coq yet. I&amp;#39;ve seen a paper about using it to generate statically verified Haskell, this might be interesting to you.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random2.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Yeah, I have read the paper too.&lt;/p&gt;
&lt;p&gt;So yes, Idris is not really ready for prime time, although it goes a long way towards making DT more amenable to normal programmers like me. Coq has a “large” community, is well supported, with a lot of libraries and tooling AFAICT so it seems a safe choice. I am curious about the situation with Agda.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/effectfully&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/effectfully.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Roman Kireev&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;The answer to “which language to choose” highly depends on whether you&amp;#39;re going to actually run code written in a DT language or just want to prove properties of some model.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random2.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I don’t plan to run code (yet).&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/effectfully&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/effectfully.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Roman Kireev&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Agda is almost unusable on the run-a-program side – it doesn&amp;#39;t have a mature proof-automation machinery. Agda is really good at modelling, meaning you can write a very powerful and convenient eDSL.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I think the most exciting option is &lt;code style=&#34;white-space: nowrap&#34;&gt;-XDependentHaskell&lt;/code&gt; (when it&amp;#39;s done) if you want to run code. I&amp;#39;ve read Richard&amp;#39;s thesis, a lot of design decisions I liked. Of course, you seem to want doing these proofs sooner than later.&lt;/p&gt;
&lt;p&gt;Since you don&amp;#39;t want to run code yet, I&amp;#39;d say pick Coq. Not for its technical merits, but because it&amp;#39;s the most mature. Proving False in Coq was a big deal, and they patched it up quickly, but in other DT languages it&amp;#39;s a regular occurrence because they are experimenting with new things, most of them are research quality. And of course there are tactics for proof automation, and libraries with these tactics, it&amp;#39;s a huge deal if you aim to prove anything bigger than toy examples for papers.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/effectfully&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/effectfully.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Roman Kireev&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Coq has an Agda-like fashion with the equations (or something like this) library. And a lot of powerful tools like &lt;a href=&#34;http://math-comp.github.io/math-comp/&#34;&gt;Ssreflect&lt;/a&gt; which can simplify complicated proofs by several magnitudes. Lean is in the same camp, but is less mature.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random2.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;This is superficial of course, but I find Coq hard to read... Might be that my Caml skills are lacking.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/effectfully&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/effectfully.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Roman Kireev&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;It is very true that Coq is hard to read. “Writing proofs in Coq is like
doing brain surgery over a telephone.”&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;First time I tried to learn Coq I found its syntax alienating (that was
a few years ago). But then I tried it a few weeks ago and found it
really pleasant, so it&amp;#39;s very subjective. You&amp;#39;ll get used to it.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random2.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;OK, so this kinda confirms that Coq might be a good way to go.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/effectfully&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/effectfully.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Roman Kireev&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;For proving, yes. For modelling Agda is top. I modelled observational type theory and cubical type theory with it, I doubt this can be done in other languages in a usable way.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-02-16-deplang-landscape"/></entry><entry><id>2018-01-25-recursion-schemes-bound</id><title type="html">“Can I use &lt;code&gt;recursion-schemes&lt;/code&gt; with &lt;code style=&#34;white-space: nowrap&#34;&gt;bound&lt;/code&gt;?”
</title><updated>2018-01-25T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-01-25-recursion-schemes-bound&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I have a question regarding recursion schemes and higher-order functors.&lt;/p&gt;
&lt;p&gt;I have an AST that, as it turns out, needs more that a couple recursive operations defined on it (substitution, evaluation, partial evaluation, etc). I thought maybe I could save myself some trouble and write them with some &lt;a href=&#34;https://hackage.haskell.org/package/recursion-schemes&#34;&gt;&lt;code&gt;recursion-schemes&lt;/code&gt;&lt;/a&gt;. I&amp;#39;ve learned that my AST is type-indexed and I&amp;#39;ll need a higher-order functor (following the post &lt;a href=&#34;http://www.timphilipwilliams.com/posts/2013-01-16-fixing-gadts.html&#34;&gt;“Fixing GADTs”&lt;/a&gt;), but I don&amp;#39;t immediately see a way to define the &lt;code style=&#34;white-space: nowrap&#34;&gt;hfmap&lt;/code&gt; for constructors that contain functions.&lt;/p&gt;
&lt;p&gt;Is there an alternate encoding of &lt;code style=&#34;white-space: nowrap&#34;&gt;Let&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Acc&lt;/code&gt; below that would allow me to define instances for &lt;code style=&#34;white-space: nowrap&#34;&gt;HFunctor&lt;/code&gt;? If not, is there a concise way to deal with something like &lt;code&gt;recursion-schemes&lt;/code&gt; for manipulating such an AST? The main requirement is that I be able to fuse multiple composite operations into single traversals.&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;c ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Symbol&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LitB&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bool&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LitI&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LitD&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Double&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Double&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LitC&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Dense&lt;/span&gt;&lt;span&gt; c &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Dense&lt;/span&gt;&lt;span&gt; c)&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LitO&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Obs&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r a&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Let&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; r a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; (r a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; r b) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r b&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;UFn&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;T.Text&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; (a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; b) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; r a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r b&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;BFn&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;T.Text&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; (a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; bb) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; r a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; r b &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r bb&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Acc&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; (r a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; r b) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; r a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r b&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Variable&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;T.Text&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExpF&lt;/span&gt;&lt;span&gt; c r a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;You are venturing into a territory where I don&amp;#39;t have answers prepared, unfortunately. Let&amp;#39;s see. If your goal is to define type-indexed ASTs in a way that allows you to have a unified approach to defining operations, the first thing to realize is that it&amp;#39;s an open research problem. One good paper I&amp;#39;ve seen on the subject is &lt;a href=&#34;https://gallais.github.io/pdf/cpp2017.pdf&#34;&gt;“Type-and-Scope Safe Programs and Their Proofs”&lt;/a&gt;, published in 2017.&lt;/p&gt;
&lt;p&gt;Regarding using recursion schemes for this purpose, a higher-order functor indeed sounds like something that could work here. I&amp;#39;ll report back with my thoughts when I read the blog post you linked.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Okay, I&amp;#39;ve read the post. That&amp;#39;s indeed a reasonable approach, matches what I had in mind when I&amp;#39;ve heard “higher-order functor” :)&lt;/p&gt;
&lt;p&gt;I see that the reason you have functions in your AST is that you&amp;#39;re using HOAS. I don&amp;#39;t think it&amp;#39;s compatible with recursion schemes, at least I haven&amp;#39;t seen it anywhere. And you lose other desirable properties with this representation (such as cheap alpha-equivalence checking). Did you consider other strategies to represent binding? Edward Kmett &lt;a href=&#34;https://www.schoolofhaskell.com/user/edwardk/bound&#34;&gt;covers them on School of Haskell&lt;/a&gt;, with pros and cons.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Oi, another problem that isn&amp;#39;t going to be solved overnight, then. I guess I can either find a different encoding of lets and lambdas or I can retool everything to work with &lt;a href=&#34;https://hackage.haskell.org/package/bound&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;bound&lt;/code&gt;&lt;/a&gt;. I&amp;#39;ve asked on Reddit if anyone knows about examples of the former. If there&amp;#39;s no good solution I suppose I&amp;#39;ll have to go with &lt;code style=&#34;white-space: nowrap&#34;&gt;bound&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;bound&lt;/code&gt; as a library won&amp;#39;t play well with recursion schemes either, but you can reuse the general approach.&lt;/p&gt;
&lt;p&gt;But I&amp;#39;d say the benefits that &lt;code style=&#34;white-space: nowrap&#34;&gt;bound&lt;/code&gt; brings outweigh those of &lt;code&gt;recursion-schemes&lt;/code&gt;, if you find yourself choosing.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Yes, I&amp;#39;m sure there are additional benefits. But I understand &lt;code&gt;recursion-schemes&lt;/code&gt; (for the most part) already, so there&amp;#39;s that... We&amp;#39;ll see if anyone gives me an answer.&lt;/p&gt;
&lt;p&gt;Can I fuse multiple operations in a single traversal with &lt;code style=&#34;white-space: nowrap&#34;&gt;bound&lt;/code&gt;?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;That&amp;#39;s not something the library provides, no. But I don&amp;#39;t think that &lt;code style=&#34;white-space: nowrap&#34;&gt;bound&lt;/code&gt; precludes you from writing code in the style of recursion schemes and from getting fusion. Your data type parameter will be used for binding rather than subexpressions, but this doesn&amp;#39;t preclude you from having another parameter.&lt;/p&gt;
&lt;p&gt;You won&amp;#39;t get to reuse existing combinators from &lt;code&gt;recursion-schemes&lt;/code&gt;, though.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I don&amp;#39;t mind the combinators, they seem to be straight forward to ad-hoc once you get a &lt;code style=&#34;white-space: nowrap&#34;&gt;*Functor&lt;/code&gt; on the datatype. I&amp;#39;ve read that &lt;code&gt;recursion-schemes&lt;/code&gt; are difficult to work with in &lt;code style=&#34;white-space: nowrap&#34;&gt;bound&lt;/code&gt; because of the polymorphism, maybe it&amp;#39;s not so bad.&lt;/p&gt;
&lt;p&gt;I also have to consider the fact that I&amp;#39;m going to need to be able to store some sort of state with regards to this AST. With PHOAS, the only way I can see, is to persist all the events that affect the tree separately, and then re-evaluate the AST when we need to figure out what the new current state is (I guess basically replace all &lt;code style=&#34;white-space: nowrap&#34;&gt;lambda&lt;/code&gt; terms with data-base positions so that they can be restored). It would be easier to just “dump it all” to a bytestring as one could conceivably do in &lt;code style=&#34;white-space: nowrap&#34;&gt;bound&lt;/code&gt; though former approach of event-sourcing with PHOAS has the ability to “replay” the system should something get erroneously computed. I&amp;#39;m not sure which in the end is the stronger case.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-01-25-recursion-schemes-bound"/></entry><entry><id>2018-01-09-lang-for-dependent-types</id><title type="html">What language to learn for dependent types?
</title><updated>2018-01-09T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-01-09-lang-for-dependent-types&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Do you guys know any Idris? I&amp;#39;m thinking of reading &lt;a href=&#34;https://www.manning.com/books/type-driven-development-with-idris&#34;&gt;the Idris book&lt;/a&gt; just to get a better grasp of dependent types, and then learn how to use those techniques in Haskell.&lt;/p&gt;
&lt;p&gt;I expect I&amp;#39;ll need some help at least with that second part, if not the first also.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I recommend Agda if your only goal is to learn about dependent types – it&amp;#39;s closer to Haskell, and the compiler is more mature (less bugs). And I know it better than Idris.&lt;/p&gt;
&lt;p&gt;That said, I&amp;#39;ve heard that the Idris book is a good one. So it&amp;#39;ll work as well. The basics are the same everywhere, once you grasp pi/sigma types it&amp;#39;ll be an easy ride.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Oh, wow. I didn&amp;#39;t realize Agda was close to Haskell. Idris looks almost identical.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Idris is very different because of strict evaluation, while Agda is lazy and basically is Haskell on steroids (better type system).&lt;/p&gt;
&lt;p&gt;Agda has a neat Haskell FFI, because its main backend compiles to Haskell – a good portion of the generated code is &lt;code&gt;unsafeCoerce&lt;/code&gt;, simply because Agda has verified the code already and asks GHC not to bother.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Are there good learning resources?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;That&amp;#39;s the tricky part. No beginner-friendly ones, unfortunately. So Idris still makes sense.&lt;/p&gt;
&lt;p&gt;I managed to learn Agda using the first chapter of &lt;a href=&#34;https://homotopytypetheory.org/book/&#34;&gt;the HoTT book&lt;/a&gt; and &lt;a href=&#34;http://people.inf.elte.hu/divip/AgdaTutorial/Index.html&#34;&gt;Péter Diviánszky&amp;#39;s Agda tutorial&lt;/a&gt;. It&amp;#39;s terse but good.&lt;/p&gt;
&lt;p&gt;Agda also has a well-maintained wiki with a &lt;a href=&#34;http://wiki.portal.chalmers.se/agda/pmwiki.php?n=Main.Othertutorials&#34;&gt;list of tutorials&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-01-09-lang-for-dependent-types"/></entry><entry><id>2018-01-05-dmap-keys</id><title type="html">Dependent maps with uniques or type reps as keys
</title><updated>2018-01-05T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-01-05-dmap-keys&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;How do I use a &lt;a href=&#34;https://hackage.haskell.org/package/dependent-map&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;DMap&lt;/code&gt;&lt;/a&gt; with keys from &lt;a href=&#34;https://hackage.haskell.org/package/prim-uniq&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;prim-uniq&lt;/code&gt;&lt;/a&gt;? I&amp;#39;m not sure I understand what is happening well enough to know how I should accomplish this. Have you used them before?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Haven&amp;#39;t used this package in particular, but I&amp;#39;ve made a similar thing myself in the past. Let&amp;#39;s backtrack a little so I can explain what&amp;#39;s happening there.&lt;/p&gt;
&lt;p&gt;When you have a heterogeneous collection, the problem you&amp;#39;re facing is that you need to know what type of thing you&amp;#39;re getting out of it on lookup. In a heterogeneous map (such as &lt;code style=&#34;white-space: nowrap&#34;&gt;DMap&lt;/code&gt;), assume you inserted &lt;code style=&#34;white-space: nowrap&#34;&gt;1 :: Int&lt;/code&gt; at key &lt;code style=&#34;white-space: nowrap&#34;&gt;k1&lt;/code&gt; and &lt;code&gt;&amp;quot;Hello&amp;quot; :: String&lt;/code&gt; at key &lt;code style=&#34;white-space: nowrap&#34;&gt;k2&lt;/code&gt;. Then you do &lt;code&gt;lookup k1 m&lt;/code&gt;. What type of value does it return? For this particular map, it&amp;#39;s &lt;code style=&#34;white-space: nowrap&#34;&gt;Int&lt;/code&gt;, but we know that because we&amp;#39;ve just inserted it, we keep track of it mentally. The compiler doesn&amp;#39;t, unless we encode it in the types somehow.&lt;/p&gt;
&lt;p&gt;The keys to a heterogeneous map should somehow determine the types of the values, so when we perform a lookup, we can know what result type to expect. For example, a key could be a &lt;a href=&#34;http://hackage.haskell.org/package/base/docs/Type-Reflection.html#t:TypeRep&#34;&gt;&lt;code&gt;Type.Reflection.TypeRep&lt;/code&gt;&lt;/a&gt; (added in GHC 8.2), then the key itself is a representation of value type, and naturally it determines the result type we get on lookup. Alternatively, we can have a singleton GADT where the constructor determines the type index. But there are cases when we want to generate keys on the fly (something like a singleton GADT with an infinite amount of constructors, if that makes any sense). Then we can use &lt;code style=&#34;white-space: nowrap&#34;&gt;Integer&lt;/code&gt;s as keys, where each key comes from a supply of unique values. When we generate a new unique key, we assign a type to it, so we can say “Let&amp;#39;s generate a new key for a &lt;code style=&#34;white-space: nowrap&#34;&gt;String&lt;/code&gt; that I want to store”, and if we do that in &lt;code style=&#34;white-space: nowrap&#34;&gt;IO&lt;/code&gt;, we can get something like &lt;code&gt;Tag (Uniq 12414123) :: Tag RealWorld String&lt;/code&gt;. From now on we know that whatever is stored at key &lt;code style=&#34;white-space: nowrap&#34;&gt;12414123&lt;/code&gt; must be of type &lt;code style=&#34;white-space: nowrap&#34;&gt;String&lt;/code&gt;, and we know that when we do a lookup as well.&lt;/p&gt;
&lt;p&gt;So imagine you have a global GADT like this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tags&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;T1&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tags&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Integer&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;T2&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tags&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;String&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;T3&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tags&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then &lt;code style=&#34;white-space: nowrap&#34;&gt;getUniq&lt;/code&gt; adds a new constructor to this GADT, and returns it. You must not lose it, because you won&amp;#39;t get access to it again.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Ok, then it functions as I thought. In terms of losing the keys, however, I can&amp;#39;t see much utility in keeping opaque keys around. If I have keys &lt;code style=&#34;white-space: nowrap&#34;&gt;x&lt;/code&gt;, &lt;code style=&#34;white-space: nowrap&#34;&gt;y&lt;/code&gt;, &lt;code style=&#34;white-space: nowrap&#34;&gt;z&lt;/code&gt;, and a &lt;code style=&#34;white-space: nowrap&#34;&gt;DMap&lt;/code&gt;, which values do those keys refer to in the map? How do I keep track of it?&lt;/p&gt;
&lt;p&gt;I also thought, but did not confirm, that if I added to a &lt;code style=&#34;white-space: nowrap&#34;&gt;DMap&lt;/code&gt; with
the following:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;tmp ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;PrimMonad&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; m (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;DMap&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tag&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;PrimState&lt;/span&gt;&lt;span&gt; m)) (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ValidDatum&lt;/span&gt;&lt;span&gt; f))&lt;/span&gt;
&lt;span&gt;tmp &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;  x &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; newTag&lt;/span&gt;
&lt;span&gt;  y &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; newTag&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;pure&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;
&lt;span&gt;    DM.fromList [ x &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;MkValidDatum&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Age&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;24&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;                , y &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;MkValidDatum&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Width&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;33&lt;/span&gt;&lt;span&gt;) ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and I wanted to access &lt;code style=&#34;white-space: nowrap&#34;&gt;Age&lt;/code&gt; at some point down the line, then I could initialize a different &lt;code style=&#34;white-space: nowrap&#34;&gt;DMap&lt;/code&gt; with a tag that witnesses the same type and then use that to pull out the original value:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;find (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Rec&lt;/span&gt;&lt;span&gt; dm _) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;  mx &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; newTag&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;let&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; DM.fromList [mx &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;MkValidDatum&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Width&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;0&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;
&lt;span&gt;      &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Just&lt;/span&gt;&lt;span&gt; mv &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; DM.lookup mx dm&lt;/span&gt;
&lt;span&gt;  mv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;You can&amp;#39;t get anything out of the map that you return from &lt;code style=&#34;white-space: nowrap&#34;&gt;tmp&lt;/code&gt;, because you&amp;#39;ve lost the keys. Creating new keys won&amp;#39;t let you access the values that are there, even if types match. If you want a type-indexed map, you can use &lt;code style=&#34;white-space: nowrap&#34;&gt;TypeRep&lt;/code&gt; for keys.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;So, I can use &lt;code style=&#34;white-space: nowrap&#34;&gt;TypeRep&lt;/code&gt; as a key for a &lt;code style=&#34;white-space: nowrap&#34;&gt;DMap&lt;/code&gt;?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Yes, why not? But you&amp;#39;ll have only a single value of each type.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I expect only a single value of each type as the collection is like an “open” record. As to “why not”, I just wanted to confirm that we were still taking about &lt;code style=&#34;white-space: nowrap&#34;&gt;DMap&lt;/code&gt;s. I&amp;#39;ll give that a go later today.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;[...] I&amp;#39;ve looked at the &lt;code style=&#34;white-space: nowrap&#34;&gt;Reflection&lt;/code&gt; module, it looks like I&amp;#39;m going to have to define &lt;code&gt;GCompare TypeRep&lt;/code&gt; instances to make &lt;code style=&#34;white-space: nowrap&#34;&gt;TypeRep&lt;/code&gt; a valid key. Will try to get to this tomorrow. I also came across &lt;a href=&#34;https://hackage.haskell.org/package/type-map&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;type-map&lt;/code&gt;&lt;/a&gt; which looks to be exactly what I need.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Defining &lt;code style=&#34;white-space: nowrap&#34;&gt;GCompare&lt;/code&gt; for &lt;code style=&#34;white-space: nowrap&#34;&gt;TypeRep&lt;/code&gt; should be easy, I will create a PR to &lt;code&gt;dependent-map&lt;/code&gt; this evening. Here you go: &lt;a href=&#34;https://github.com/mokus0/dependent-sum/pull/17&#34;&gt;PR #17&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-01-05-dmap-keys"/></entry><entry><id>2018-01-03-stack-reruns-tests</id><title type="html">Stack reruns passed tests even with &lt;code&gt;--no-rerun-tests&lt;/code&gt;
</title><updated>2018-01-03T00:00:00Z</updated><content type="html">&lt;div id=&#34;2018-01-03-stack-reruns-tests&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random1.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;It looks like Stack does not properly track what tests have passed? It has option &lt;code&gt;--no-rerun-tests&lt;/code&gt; that should remember when the tests have passed and avoid rerunning them during &lt;code style=&#34;white-space: nowrap&#34;&gt;stack test&lt;/code&gt;, but for me it always reruns the tests, even with no code changes and the previous run having them pass.&lt;/p&gt;
&lt;p&gt;Is that a bug or is there something more I need to be doing?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I&amp;#39;ve investigated and it turns out that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It is a bug in Stack.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--no-rerun-tests&lt;/code&gt; is broken &lt;em&gt;completely&lt;/em&gt;, it can&amp;#39;t ever work with Stack 1.6.1, on any project. It&amp;#39;s been broken since Nov 4, 2015. The Stack team has noticed only now, apparently.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There is a workaround: when tests succeed, find a file called &lt;code&gt;stack-test-success&lt;/code&gt; in your Stack directory and change the last byte from 0 to 1 :) Stack should be doing it by itself when tests pass but it doesn&amp;#39;t.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I&amp;#39;ve asked &lt;a href=&#34;https://github.com/mgsloan&#34;&gt;Michael Sloan&lt;/a&gt; what would be the best way to fix the bug. (It&amp;#39;s going to be a one-line change, the only question is “what is the best place to put that line”.) I&amp;#39;ll ping you when my PR is accepted and the bug is fixed in HEAD.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Update: I&amp;#39;ve &lt;a href=&#34;https://github.com/commercialhaskell/stack/pull/3770&#34;&gt;fixed the bug&lt;/a&gt; and the next release of Stack (1.6.4 probably) will include the fix. You can also use the &lt;code style=&#34;white-space: nowrap&#34;&gt;stable&lt;/code&gt; branch of Stack if you want to.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random1.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Very cool! Looking forward to that release then. Thanks a bunch.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2018-01-03-stack-reruns-tests"/></entry><entry><id>2017-12-27-injectivity</id><title type="html">What does “injective” mean in the context of type families?
</title><updated>2017-12-27T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-12-27-injectivity&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Can you explain what is meant by “injective”? Sometimes I get type errors surrounding that word. I know it has something to do with type families.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Injectivity means that we can determine the input to a function from its output. For example, &lt;code&gt;\b -&amp;gt; if b then 1 else 0&lt;/code&gt; is an injective function, because we can look at its output (1 or 0) and deduce the corresponding input.&lt;/p&gt;
&lt;p&gt;Formally, you would say that a function &lt;code style=&#34;white-space: nowrap&#34;&gt;f&lt;/code&gt; is injective when &lt;code style=&#34;white-space: nowrap&#34;&gt;f a == f b&lt;/code&gt; implies &lt;code style=&#34;white-space: nowrap&#34;&gt;a == b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since you are seeing this in the context of type families, this is probably what you are getting from GHC:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;NB: `F&amp;#39; is a type function, and may not be injective
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case GHC is just trying to help you understand why it cannot deduce the necessary type equalities.&lt;/p&gt;
&lt;p&gt;The typechecker relies on two facts about type constructors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
they are injective: &lt;code style=&#34;white-space: nowrap&#34;&gt;T a ~ T b&lt;/code&gt; implies &lt;code style=&#34;white-space: nowrap&#34;&gt;a ~ b&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
they are generative: &lt;code style=&#34;white-space: nowrap&#34;&gt;T a ~ D b&lt;/code&gt; implies &lt;code style=&#34;white-space: nowrap&#34;&gt;T ~ D&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These properties hold for &lt;code style=&#34;white-space: nowrap&#34;&gt;data&lt;/code&gt;, &lt;code&gt;data family&lt;/code&gt;, &lt;code style=&#34;white-space: nowrap&#34;&gt;newtype&lt;/code&gt;, &lt;code style=&#34;white-space: nowrap&#34;&gt;class&lt;/code&gt;. They do not necessarily hold for a &lt;code style=&#34;white-space: nowrap&#34;&gt;type&lt;/code&gt; synonym or a &lt;code&gt;type family&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When you have a type function with a signature like this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;f ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Num&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;the compiler needs to know &lt;code style=&#34;white-space: nowrap&#34;&gt;a&lt;/code&gt; to find the &lt;code style=&#34;white-space: nowrap&#34;&gt;Num&lt;/code&gt; instance for it. When you pass an argument of type &lt;code style=&#34;white-space: nowrap&#34;&gt;Maybe Int&lt;/code&gt; to it, GHC uses injectivity of &lt;code style=&#34;white-space: nowrap&#34;&gt;Maybe&lt;/code&gt; to conclude that &lt;code style=&#34;white-space: nowrap&#34;&gt;a&lt;/code&gt; is &lt;code style=&#34;white-space: nowrap&#34;&gt;Int&lt;/code&gt;, and finds an instance for it, and all is well.&lt;/p&gt;
&lt;p&gt;But assume the input was a type family:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;family&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;F&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;F&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;F&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Char&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;

&lt;span class=&#34;ot&#34;&gt;f ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Num&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;F&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you pass &lt;code style=&#34;white-space: nowrap&#34;&gt;Maybe Int&lt;/code&gt; to &lt;code style=&#34;white-space: nowrap&#34;&gt;f&lt;/code&gt;, but GHC cannot deduce that &lt;code style=&#34;white-space: nowrap&#34;&gt;a&lt;/code&gt; is &lt;code style=&#34;white-space: nowrap&#34;&gt;Int&lt;/code&gt;, because &lt;code&gt;F a ~ Maybe Int&lt;/code&gt; for both &lt;code style=&#34;white-space: nowrap&#34;&gt;Int&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Char&lt;/code&gt; – the &lt;code style=&#34;white-space: nowrap&#34;&gt;F&lt;/code&gt; type family is not injective.&lt;/p&gt;
&lt;p&gt;Since GHC 8.0.1 you can annotate your type families as injective (see &lt;a href=&#34;http://ghc.readthedocs.io/en/latest/glasgow_exts.html#injective-type-families&#34;&gt;“Injective type families”&lt;/a&gt; in the GHC manual). For example:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;family&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&amp;#39;&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&amp;#39;&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bool&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&amp;#39;&lt;/span&gt;&lt;span&gt; a  &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of course, if the type family is not actually injective, GHC will report a type error.&lt;/p&gt;
&lt;p&gt;By the way, you can notice that the syntax of injectivity annotations is modelled after the syntax of functional dependencies. This is no coincidence, and the extension is actually called &lt;code style=&#34;white-space: nowrap&#34;&gt;-XTypeFamilyDependencies&lt;/code&gt;. However, it is an immature extension: you cannot have more than one dependency for a single type family, or a dependency that involves several type variables. In addition, there are issues with type families (presented the talk &lt;a href=&#34;https://www.youtube.com/watch?v=AGJY95Otb9U&#34;&gt;“Constrained Type Families”&lt;/a&gt; from ICFP 2017) that prevent GHC from using the injectivity annotation in certain cases.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Wow! That&amp;#39;s very clear and helpful! Thank you very much.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I&amp;#39;ve also looked at GHC sources to understand in what circumstances exactly GHC emits this hint about injectivity. Here&amp;#39;s the relevant code:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;tyfun_msg &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Just&lt;/span&gt;&lt;span&gt; tc1 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; mb_fun1&lt;/span&gt;
&lt;span&gt;          , &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Just&lt;/span&gt;&lt;span&gt; tc2 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; mb_fun2&lt;/span&gt;
&lt;span&gt;          , tc1 &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;==&lt;/span&gt;&lt;span&gt; tc2&lt;/span&gt;
&lt;span&gt;          , &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;not&lt;/span&gt;&lt;span&gt; (isInjectiveTyCon tc1 &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Nominal&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;          &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; text &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;NB:&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;+&amp;gt;&lt;/span&gt;&lt;span&gt; quotes (ppr tc1)&lt;/span&gt;
&lt;span&gt;            &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;+&amp;gt;&lt;/span&gt;&lt;span&gt; text &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;is a non-injective type family&amp;quot;&lt;/span&gt;
&lt;span&gt;          &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;otherwise&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; empty&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and the nearby comment is:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;co&#34;&gt;-- (b) warning about injectivity if both sides are the same&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;--     type function application   F a ~ F b&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;--     See Note [Non-injective type functions]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, you will be getting this hint whenever GHC tries to unify &lt;code style=&#34;white-space: nowrap&#34;&gt;F a&lt;/code&gt; with &lt;code style=&#34;white-space: nowrap&#34;&gt;F b&lt;/code&gt;, knowing that &lt;code style=&#34;white-space: nowrap&#34;&gt;F&lt;/code&gt; is not injective. The actual error might be something else, this is more of a reminder. Again, from the source:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;co&#34;&gt;{-&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;Note [Non-injective type functions]&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;It&amp;#39;s very confusing to get a message like&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;     Couldn&amp;#39;t match expected type `Depend s&amp;#39;&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;            against inferred type `Depend s1&amp;#39;&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;so mkTyFunInfoMsg adds:&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;       NB: `Depend&amp;#39; is type function, and hence may not&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;            be injective&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-12-27-injectivity"/></entry><entry><id>2017-12-22-arrows</id><title type="html">When would one use arrows?
</title><updated>2017-12-22T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-12-22-arrows&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Arrows.&lt;/p&gt;
&lt;p&gt;I know nothing about them.&lt;/p&gt;
&lt;p&gt;Why would you use them?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;There aren&amp;#39;t too many use cases for them. They are used in FRP (see &lt;a href=&#34;https://hackage.haskell.org/package/netwire&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;netwire&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://hackage.haskell.org/package/wires&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;wires&lt;/code&gt;&lt;/a&gt;), to form SQL queries (&lt;a href=&#34;https://hackage.haskell.org/package/opaleye&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;opaleye&lt;/code&gt;&lt;/a&gt;), but I must admit I don&amp;#39;t understand exactly how they are used there (except I know that the author of &lt;code style=&#34;white-space: nowrap&#34;&gt;opaleye&lt;/code&gt; mentioned once that if he had to rewrite it from scratch, he wouldn&amp;#39;t use arrows).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2018-03-05:&lt;/strong&gt; the author of &lt;code style=&#34;white-space: nowrap&#34;&gt;opaleye&lt;/code&gt; &lt;a href=&#34;https://reddit.com/r/haskell/comments/824zn6/dirt_cheap_haskell_publishing_our_answers_to_our/dv7hh7n/&#34;&gt;chimes in on Reddit&lt;/a&gt; and says that he didn&amp;#39;t quite say that; “There&amp;#39;s no getting away from the fact that, in the denotation Opaleye uses, SQL queries are arrows and not monads [...] If I write the tutorial again I might deemphasize arrows. Since Opaleye was written GHC has gained &lt;code&gt;ApplicativeDo&lt;/code&gt; which allows one to write a lot of queries without arrows at all.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;thumbnail thumbnail-right thumbnail-code&#34;&gt;&lt;a href=&#34;https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#arrow-notation&#34;&gt;&lt;img src=&#34;https://monadfix.com/thumbnails/proc-notation.png&#34; srcset=&#34;https://monadfix.com/thumbnails/2x_proc-notation.png 2x&#34;&gt;&lt;/a&gt;&lt;p class=&#34;thumbnail-caption&#34;&gt;An example of &lt;code style=&#34;white-space: nowrap&#34;&gt;proc&lt;/code&gt;-notation in code that uses &lt;a href=&#34;https://hackage.haskell.org/package/opaleye&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;opaleye&lt;/code&gt;&lt;/a&gt;
&lt;/p&gt;&lt;/div&gt;&lt;p&gt;The main advantage you get from arrows is the &lt;code style=&#34;white-space: nowrap&#34;&gt;proc&lt;/code&gt; notation, which I haven&amp;#39;t really used either. And the &lt;code style=&#34;white-space: nowrap&#34;&gt;proc&lt;/code&gt; notation implementation is hardly maintained anyway, Simon talked about it on the mailing list, no one understands how it works in GHC nowadays, especially its interactions with &lt;code style=&#34;white-space: nowrap&#34;&gt;-XRebindableSyntax&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Basically, when you design an API, your type might turn out to be an arrow, and then you get &lt;code style=&#34;white-space: nowrap&#34;&gt;proc&lt;/code&gt;-notation, but other than that I wouldn&amp;#39;t bother. A sign that your type might be an arrow is that it is a profunctor that supports &lt;code&gt;(-&amp;gt;) a b -&amp;gt; p a b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you want to understand monads, generally the progression is to first understand &lt;code style=&#34;white-space: nowrap&#34;&gt;Functor&lt;/code&gt; and &lt;code&gt;Applicative&lt;/code&gt;, because they are morally the superclasses of &lt;code style=&#34;white-space: nowrap&#34;&gt;Monad&lt;/code&gt; (even though in the standard library it wasn&amp;#39;t the case for a long time). Similarly, to understand arrows you must first understand profunctors, then profunctor composition, and then strong profunctors.&lt;/p&gt;
&lt;p&gt;The point is that arrows are a very specific point in the design space. Even profunctors are a rare occasion in code, not to mention strong monoidal profunctors (aka arrows).&lt;/p&gt;
&lt;div class=&#34;thumbnail thumbnail-right thumbnail-page&#34;&gt;&lt;a href=&#34;http://www.cse.chalmers.se/~rjmh/Papers/arrows.pdf&#34;&gt;&lt;img src=&#34;https://monadfix.com/thumbnails/arrows-hughes.png&#34; srcset=&#34;https://monadfix.com/thumbnails/2x_arrows-hughes.png 2x&#34;&gt;&lt;/a&gt;&lt;p class=&#34;thumbnail-caption&#34;&gt;Generalising Monads to Arrows (Hughes 1998)
&lt;/p&gt;&lt;/div&gt;&lt;p&gt;I mean, if they weren&amp;#39;t in base, they would probably be an obscure library on Hackage that 2.5 people knew about. I tried to learn them a few years ago, I found the original paper (&lt;a href=&#34;http://www.cse.chalmers.se/~rjmh/Papers/arrows.pdf&#34;&gt;“Generalising Monads to Arrows”&lt;/a&gt;) quite approachable, but since then I have seen exactly zero use cases for arrows in my code, so now I don&amp;#39;t even remember the specifics. People import &lt;code&gt;Control.Arrow&lt;/code&gt; to get tuple combinators :)&lt;/p&gt;
&lt;p&gt;And Ed. Kmett refers to them as a “historical accident”.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Thank you for the historical context! I think I&amp;#39;ll read through &lt;a href=&#34;https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/&#34;&gt;Category Theory for Programmers&lt;/a&gt; then, instead of studying arrows.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-12-22-arrows"/></entry><entry><id>2017-12-20-log-types</id><title type="html">Machine-readable logs with distinct ADTs for log messages
</title><updated>2017-12-20T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-12-20-log-types&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random3.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;All my log statements are represented as ADTs. I have many log data types scattered through the code; if I had only one type to capture all log statements, I would have a dependency sink and every time I dot an ‘i’ in log I would have to recompile entire application.&lt;/p&gt;
&lt;p&gt;I log in JSON so all those ADTs implement &lt;code style=&#34;white-space: nowrap&#34;&gt;ToJSON&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;FromJSON&lt;/code&gt;. I also have a separate application which takes the logs and converts them back to ADTs, and I have &lt;code style=&#34;white-space: nowrap&#34;&gt;Pretty&lt;/code&gt; instances for all those ADTs – to print log statements in human-readable form.&lt;/p&gt;
&lt;p&gt;The problem is dispatch. When I read a JSON object I have a string which identifies the type, but my dispatch basically looks like a very long list of:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;LogScheduleTx&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; render (parse&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; logEntry ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Either&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Err&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogScheduleTx&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Is there a better way to do this dispatch?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Okay, how do you envision this tool would figure out which types to try to parse from logs?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Some explicit specification, like &lt;code&gt;type LogTypes = &amp;#39;[LogX, LogY, LogZ]&lt;/code&gt;? This list could be at top level, where you don&amp;#39;t need to recompile.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Figure out the types from the scope, i.e. the logic could be “any type with a &lt;code&gt;IsLogMessage&lt;/code&gt; instance”?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random3.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I can have any. I am not sure how the typeclass solution would work but indeed perhaps a type list would do the trick.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Okay, so here&amp;#39;s how it could work. First, define a class:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogTag&lt;/span&gt;&lt;span&gt; t &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;  logTag ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Proxy&lt;/span&gt;&lt;span&gt; t &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All log types would define instances for it:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogTag&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogInfoX&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  logTag _ &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;X&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is needed because we want to associate a string to each type. This string will appear in the generated JSON to identify the type. Any module that defines a type for logging would depend on this class, but it&amp;#39;s unlikely to change, so this would not cause recompilation.&lt;/p&gt;
&lt;p&gt;For logging messages, you&amp;#39;d have a helper like this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;logObject ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogTag&lt;/span&gt;&lt;span&gt; t &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; t &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Aeson.Value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It would construct a JSON object with two fields:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;&lt;span class=&#34;fu&#34;&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;er&#34;&gt;tag&lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;er&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;er&#34;&gt;...&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and we&amp;#39;d know that any log message has a tag that we can read. If I understand correctly, this is pretty similar to what you have now: you already have a tag that you match on.&lt;/p&gt;
&lt;p&gt;The last bit is to define &lt;code style=&#34;white-space: nowrap&#34;&gt;FromJSON&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Pretty&lt;/code&gt; in a generic way for the type-level list of the messages. You could do it with a union of types in the style of &lt;a href=&#34;https://hackage.haskell.org/package/union&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;union&lt;/code&gt;&lt;/a&gt;. Ideally we&amp;#39;d want the following API:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;*&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- a sum type for all log types&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogTypes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogX&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogY&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogZ&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;

&lt;span class=&#34;ot&#34;&gt;parseLogTypes ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Aeson.Value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogTypes&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;prettyLogTypes ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogTypes&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Doc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;AnsiStyle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If this sounds right to you, I can describe how to implement
&lt;code&gt;parseLogTypes&lt;/code&gt; and &lt;code&gt;prettyLogTypes&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random3.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;This all makes sense. Indeed I have the first part done (I did it with &lt;code style=&#34;white-space: nowrap&#34;&gt;Typeable&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;A trouble with &lt;code style=&#34;white-space: nowrap&#34;&gt;Typeable&lt;/code&gt; is that the type rep can change between compiler versions, while a string is stable.&lt;/p&gt;
&lt;p&gt;Now to the solution. First we need &lt;code style=&#34;white-space: nowrap&#34;&gt;LogUnion&lt;/code&gt;, which is trivial to define:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; ts &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LThis&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;!&lt;/span&gt;&lt;span&gt;t &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; (t &amp;#39;&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:&lt;/span&gt;&lt;span&gt; ts)&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LThat&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; ts) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; (t &amp;#39;&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:&lt;/span&gt;&lt;span&gt; ts)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then we&amp;#39;d want to implement &lt;code style=&#34;white-space: nowrap&#34;&gt;FromJSON&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Pretty&lt;/code&gt; for it. This would require two instances of these classes: the base case and induction.&lt;/p&gt;
&lt;p&gt;The base case is an empty list of types. &lt;code style=&#34;white-space: nowrap&#34;&gt;parseJSON&lt;/code&gt; would always throw a parsing error (because an empty union is the same as &lt;code style=&#34;white-space: nowrap&#34;&gt;Void&lt;/code&gt;, and there are no values to construct). &lt;code style=&#34;white-space: nowrap&#34;&gt;pretty&lt;/code&gt; does no job either, because it receives an empty union (which is similar to &lt;code style=&#34;white-space: nowrap&#34;&gt;Void&lt;/code&gt;), and this cannot happen at runtime. Thus:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FromJSON&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; &amp;#39;[]) &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  parseJSON _ &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;fail&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;not a valid log message&amp;quot;&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pretty&lt;/span&gt;&lt;span&gt; &amp;#39;[] &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  pretty &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;case&lt;/span&gt;&lt;span&gt; {} &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- see the EmptyCase extension&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the interesting work would be happening in the inductive case:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogTag&lt;/span&gt;&lt;span&gt; t, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FromJSON&lt;/span&gt;&lt;span&gt; t, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FromJSON&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; ts)) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FromJSON&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; (t &amp;#39;&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:&lt;/span&gt;&lt;span&gt; ts))&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;    parseJSON j &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; withObject &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;LogObject&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; \o &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;      tag &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; o &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;
&lt;span&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;if&lt;/span&gt;&lt;span&gt; tag &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;==&lt;/span&gt;&lt;span&gt; logTag (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Proxy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span&gt;t)&lt;/span&gt;
&lt;span&gt;        &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;then&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;          message &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; o &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;message&amp;quot;&lt;/span&gt;
&lt;span&gt;          &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;This&lt;/span&gt;&lt;span&gt; message&lt;/span&gt;
&lt;span&gt;        &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;else&lt;/span&gt;
&lt;span&gt;          &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;That&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span&gt; parseJSON j&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we check the string tag (or type rep, if you go with the &lt;code style=&#34;white-space: nowrap&#34;&gt;Typeable&lt;/code&gt; solution). In case it matches the head of the list, we try to parse the message of this type &lt;code style=&#34;white-space: nowrap&#34;&gt;t&lt;/code&gt;. Otherwise we delegate the work to the instance for the rest of the list. Eventually either the tag would match, or we&amp;#39;d get to the base case and fail.&lt;/p&gt;
&lt;p&gt;A similar thing for &lt;code style=&#34;white-space: nowrap&#34;&gt;pretty&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pretty&lt;/span&gt;&lt;span&gt; t, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pretty&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; ts)) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pretty&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogUnion&lt;/span&gt;&lt;span&gt; (t &amp;#39;&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:&lt;/span&gt;&lt;span&gt; ts))&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;    pretty (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;This&lt;/span&gt;&lt;span&gt; t) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; pretty t&lt;/span&gt;
&lt;span&gt;    pretty (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;That&lt;/span&gt;&lt;span&gt; t) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; pretty t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-12-20-log-types"/></entry><entry><id>2017-12-19-gadts-to-json</id><title type="html">“Converting GADTs to JSON without boilerplate?”
</title><updated>2017-12-19T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-12-19-gadts-to-json&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random3.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;We want to log the effects. Basically every time I evaluate an effect I would like to issue a log statement before and just after. It could be done almost without any effort, but our effects are represented with a GADT, and I cannot easly convert it to JSON. Basically for now I have to write things like:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;DBAction&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;AddRequest&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;   ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RequestId&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;DBAction&lt;/span&gt;&lt;span&gt; ()&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;GetValue&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;     ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RequestId&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;DBAction&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Either&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Value&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;PersistEvent&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Event&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;DBAction&lt;/span&gt;&lt;span&gt; ()&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- more constructors omitted&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBAction&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBActionAddRequest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RequestId&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBActionGetValue&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;RequestId&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBActionPersistEvent&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Event&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- ...&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;deriving&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Generic&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ToJSON&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBAction&lt;/span&gt;
&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FromJSON&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBAction&lt;/span&gt;

&lt;span class=&#34;ot&#34;&gt;toStartLog ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;DBAction&lt;/span&gt;&lt;span&gt; c &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBAction&lt;/span&gt;
&lt;span&gt;toStartLog (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;AddRequest&lt;/span&gt;&lt;span&gt; r)   &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBActionAddRequest&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;
&lt;span&gt;toStartLog (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;GetValue&lt;/span&gt;&lt;span&gt; r)     &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBActionGetValue&lt;/span&gt;&lt;span&gt; r&lt;/span&gt;
&lt;span&gt;toStartLog (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;PersistEvent&lt;/span&gt;&lt;span&gt; e) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;LogDBActionPersistEvent&lt;/span&gt;&lt;span&gt; e&lt;/span&gt;
&lt;span class=&#34;co&#34;&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This all is like super redundant information. I have to do it &amp;#39;cause I don’t see other way to convert this &lt;code style=&#34;white-space: nowrap&#34;&gt;DBAction a&lt;/code&gt; to and from JSON.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;This is a common problem when dealing with GADTs.&lt;/p&gt;
&lt;p&gt;You usually have several representations, which have progressively more info at type level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;String&lt;/code&gt; – you only know that you have a sequence of characters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Aeson.Value&lt;/code&gt; – you know that these characters represent a valid JSON
document&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;LogDBAction&lt;/code&gt; – you know that this JSON represents a DB action&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;DBAction&lt;/code&gt; – you know that this DB action has expected input/output
types&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There should be – in theory – a general way to convert between all these representation providing only minimal info. For example, we can convert between &lt;code&gt;LogDBAction&lt;/code&gt; and &lt;code&gt;Aeson.Value&lt;/code&gt; using &lt;code style=&#34;white-space: nowrap&#34;&gt;Generic&lt;/code&gt;, and between &lt;code&gt;Aeson.Value&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;String&lt;/code&gt; using functions that &lt;code style=&#34;white-space: nowrap&#34;&gt;aeson&lt;/code&gt; provides.&lt;/p&gt;
&lt;p&gt;The issue is the last gap between representations, &lt;code&gt;LogDBAction&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;DBAction&lt;/code&gt;. Ideally, it should be possible to derive &lt;code&gt;LogDBAction&lt;/code&gt; from &lt;code style=&#34;white-space: nowrap&#34;&gt;DBAction&lt;/code&gt;, together with conversion functions. In practice, everyone&amp;#39;s doing this by hand.&lt;/p&gt;
&lt;div class=&#34;thumbnail thumbnail-right thumbnail-page&#34;&gt;&lt;a href=&#34;http://www.cs.ox.ac.uk/people/timothy.zakian/ghostbuster.pdf&#34;&gt;&lt;img src=&#34;https://monadfix.com/thumbnails/ghostbuster.png&#34; srcset=&#34;https://monadfix.com/thumbnails/2x_ghostbuster.png 2x&#34;&gt;&lt;/a&gt;&lt;p class=&#34;thumbnail-caption&#34;&gt;Ghostbuster: A Tool for Simplifying and Converting GADTs (2016)
&lt;/p&gt;&lt;/div&gt;&lt;p&gt;The latest research on this topic that I&amp;#39;ve seen was a prototype tool that automates this process, I recommend reading their paper for more info (it&amp;#39;s fairly well written and understandable without too much background): &lt;a href=&#34;http://www.cs.ox.ac.uk/people/timothy.zakian/ghostbuster.pdf&#34;&gt;“Ghostbuster: A Tool for Simplifying and Converting GADTs”&lt;/a&gt;. But I am not aware of a tool on Hackage that would do this transformation.&lt;/p&gt;
&lt;p&gt;I sent an email to one of the authors of the Ghostbuster paper, asked him if the tool is still in development. When he answers, I will let you know.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random3.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Cheers, that’s very informative. Thank you – I will read the paper.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Meanwhile, I have received a reply. The author told me that he and another member of their research team had left Indiana University and the fate of the tool is uncertain.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-12-19-gadts-to-json"/></entry><entry><id>2017-12-18-undecidableinstances</id><title type="html">Don&amp;#39;t be afraid of &lt;code style=&#34;white-space: nowrap&#34;&gt;-XUndecidableInstances&lt;/code&gt;
</title><updated>2017-12-18T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-12-18-undecidableinstances&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/o1lo01ol1o&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/o1lo01ol1o.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Tim&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;[...] My issue is that I had to turn on &lt;code style=&#34;white-space: nowrap&#34;&gt;-XUndecidableInstances&lt;/code&gt; to get all the necessary instance constraints to typecheck [...]&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Before reading the code, I would like to comment on &lt;code style=&#34;white-space: nowrap&#34;&gt;-XUndecidableInstances&lt;/code&gt;. The extension is entirely benign, and is not an indication of a wrong approach. You can treat instance search as a function (you give it a type, it gives you an instance). For example, when GHC tries to fulfill an &lt;code style=&#34;white-space: nowrap&#34;&gt;Ord a&lt;/code&gt; constraint and it knows that &lt;code style=&#34;white-space: nowrap&#34;&gt;a ~ Int&lt;/code&gt;, this is like calling &lt;code&gt;findMeOrdInst :: a -&amp;gt; Ord a&lt;/code&gt; with &lt;code style=&#34;white-space: nowrap&#34;&gt;Int&lt;/code&gt; as an argument (hopefully, the analogy makes sense). In this model, each instance is a function clause.&lt;/p&gt;
&lt;p&gt;GHC really wants this function &lt;code&gt;findMeOrdInst&lt;/code&gt; to terminate, because this search is happening at type level, and we risk non-termination in the type-checker, and a hanging compiler would be a rather unpleasant experience. Of course, due to the halting problem, a perfect termination check cannot exist, so GHC uses a couple of heuristics, which are documented in the GHC manual (&lt;a href=&#34;https://ghc.readthedocs.io/en/latest/glasgow_exts.html#instance-termination&#34;&gt;“Instance Termination Rules”&lt;/a&gt;). When the heuristics reject correct code, we disable them with &lt;code style=&#34;white-space: nowrap&#34;&gt;-XUndecidableInstances&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The worst thing that can happen is that the compiler will hang, but in practice it won&amp;#39;t, because there&amp;#39;s a limit to the amount of iterations it performs doing instance search, so you&amp;#39;ll see an error about too many iterations during instance search. So, basically, &lt;code style=&#34;white-space: nowrap&#34;&gt;-XUndecidableInstances&lt;/code&gt; is a small regression to error messages in exchange for more expressive power, which is a good trade-off.&lt;/p&gt;
&lt;p&gt;For some reason people try to avoid &lt;code style=&#34;white-space: nowrap&#34;&gt;-XUndecidableInstances&lt;/code&gt;, probably because the word “undecidable” sounds bad, or because they&amp;#39;ve learned that &lt;code style=&#34;white-space: nowrap&#34;&gt;-XIncoherentInstances&lt;/code&gt; is bad (which is true) and start confusing the two.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-12-18-undecidableinstances"/></entry><entry><id>2017-12-06-digestive-functors</id><title type="html">A writeup on &lt;code&gt;digestive-functors&lt;/code&gt;
</title><updated>2017-12-06T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-12-06-digestive-functors&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random4.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I&amp;#39;ve tried using &lt;a href=&#34;https://hackage.haskell.org/package/digestive-functors&#34;&gt;&lt;code&gt;digestive-functors&lt;/code&gt;&lt;/a&gt; for creating forms in my &lt;a href=&#34;https://www.spock.li&#34;&gt;Spock&lt;/a&gt; application, but I feel lost.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;&lt;em&gt;[The following is a copy of a gist I wrote and sent. It turned out to be longer than I expected.]&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In my opinion, &lt;a href=&#34;https://hackage.haskell.org/package/digestive-functors&#34;&gt;&lt;code&gt;digestive-functors&lt;/code&gt;&lt;/a&gt; is needlessly complicated and obscure (like many Haskell libraries are). It took me three hours to understand how to work with it. However, until things like &lt;a href=&#34;https://hackage.haskell.org/package/forma&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;forma&lt;/code&gt;&lt;/a&gt; get more popular, that&amp;#39;s what we have to work with, I guess. (Oh, and &lt;code style=&#34;white-space: nowrap&#34;&gt;forma&lt;/code&gt; is kinda obscure too, though a bit less.)&lt;/p&gt;
&lt;h2 id=&#34;writing-your-own-formlets-library&#34;&gt;Writing your own formlets library&lt;/h2&gt;
&lt;p&gt;I believe that the best way to understand something is to write your own version of it, and with &lt;code&gt;digestive-functors&lt;/code&gt; it is seemingly the &lt;em&gt;only&lt;/em&gt; way to understand it. Loading the examples into GHCi shouldn&amp;#39;t be necessary, just read the explanations.&lt;/p&gt;
&lt;p&gt;We want to be able to write forms like this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;userForm &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;User&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.:&lt;/span&gt;&lt;span&gt; text &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Nothing&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;*&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;mail&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.:&lt;/span&gt;&lt;span&gt; check &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;Not an email address&amp;quot;&lt;/span&gt;&lt;span&gt; checkEmail (text &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Nothing&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then we want to be able to do two vastly different things with them:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Ignore all logic in the form and just render its structure.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;“Run” the form against a list of (field, value) pairs and produce a &lt;code style=&#34;white-space: nowrap&#34;&gt;User&lt;/code&gt; as the result.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And now, a spoiler: whenever you want to be able to run something &lt;em&gt;and&lt;/em&gt; to inspect the structure, it&amp;#39;s often going to look like something from the &lt;code style=&#34;white-space: nowrap&#34;&gt;Free&lt;/code&gt;-land. In our case, we can simply create a data type with special constructors for &lt;code style=&#34;white-space: nowrap&#34;&gt;pure&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;&amp;lt;*&amp;gt;&lt;/code&gt;, and that will give us a way to represent all form definitions in an inspectable way.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a simplified version of &lt;code style=&#34;white-space: nowrap&#34;&gt;Form&lt;/code&gt; from &lt;code&gt;digestive-functors&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE GADTs #-}&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Data.Text&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Text&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Text&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pure&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Ap&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;   ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; (b &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; a) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Text&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Text&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Checkbox&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;  ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In case you are not familiar with the GADTs syntax, it&amp;#39;s the same as:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pure&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Ap&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; (b &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; a)) (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; b)&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Name&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Checkbox&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The difference is that the GADTs syntax lets us specify that the &lt;code style=&#34;white-space: nowrap&#34;&gt;TextField&lt;/code&gt; constructor can only be used to construct a &lt;code style=&#34;white-space: nowrap&#34;&gt;Form Text&lt;/code&gt;, not any arbitrary &lt;code style=&#34;white-space: nowrap&#34;&gt;Form a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The second two constructors (&lt;code style=&#34;white-space: nowrap&#34;&gt;TextField&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Checkbox&lt;/code&gt;) are easy – they let us create labelled inputs. (In &lt;code&gt;digestive-functors&lt;/code&gt; they can also contain values, weirdly. It doesn&amp;#39;t make sense to me, because when you&amp;#39;re &lt;em&gt;describing&lt;/em&gt; a form it doesn&amp;#39;t make sense to also fill it – the values are supposed to be provided by the user. I have spent some time thinking about it and I don&amp;#39;t see a good reason for this design, so in my toy realization I&amp;#39;m going to omit this detail.)&lt;/p&gt;
&lt;p&gt;The first two constructors are used for sticking together the components of the form. In the next section we&amp;#39;ll see how it&amp;#39;s done.&lt;/p&gt;
&lt;h3 id=&#34;creating-a-form&#34;&gt;Creating a form&lt;/h3&gt;
&lt;p&gt;We construct forms with &lt;code style=&#34;white-space: nowrap&#34;&gt;&amp;lt;$&amp;gt;&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;&amp;lt;*&amp;gt;&lt;/code&gt;, so our &lt;code style=&#34;white-space: nowrap&#34;&gt;Form&lt;/code&gt; must have an &lt;code&gt;Applicative&lt;/code&gt; instance and a &lt;code style=&#34;white-space: nowrap&#34;&gt;Functor&lt;/code&gt; instance. The &lt;code style=&#34;white-space: nowrap&#34;&gt;Pure&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Ap&lt;/code&gt; constructors are exactly what we need to write it:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Functor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;fmap&lt;/span&gt;&lt;span&gt; f &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Ap&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pure&lt;/span&gt;&lt;span&gt; f)&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Applicative&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;pure&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pure&lt;/span&gt;
&lt;span&gt;  (&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;*&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Ap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can construct simple forms that become trees of &lt;code style=&#34;white-space: nowrap&#34;&gt;Ap&lt;/code&gt;s:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;registerForm &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;User&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span&gt;       &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;*&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span&gt;       &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;*&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class=&#34;co&#34;&gt;-- is the same as&lt;/span&gt;

&lt;span&gt;registerForm &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Ap&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Ap&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Ap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;User&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;
&lt;span&gt;         (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;
&lt;span&gt;     (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Thanks to currying, a chain of any length becomes a nested &lt;code style=&#34;white-space: nowrap&#34;&gt;Ap&lt;/code&gt; application. If some elements were complex forms instead of single fields, it would&amp;#39;ve still been a tree of &lt;code style=&#34;white-space: nowrap&#34;&gt;Ap&lt;/code&gt;s, though the structure would&amp;#39;ve been a bit more complex.&lt;/p&gt;
&lt;h3 id=&#34;rendering-a-form&#34;&gt;Rendering a form&lt;/h3&gt;
&lt;p&gt;A tree like that is very easy to render – just walk through it and render all fields/checkboxes. I&amp;#39;m going to use &lt;code style=&#34;white-space: nowrap&#34;&gt;printf&lt;/code&gt; for simplicity, though in real life you should use &lt;a href=&#34;https://hackage.haskell.org/package/lucid&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;lucid&lt;/code&gt;&lt;/a&gt; or something similar for such tasks.&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;renderForm ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;String&lt;/span&gt;
&lt;span&gt;renderForm f &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;lt;form&amp;gt;&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;++&lt;/span&gt;&lt;span&gt; go f &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;++&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;lt;/form&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;    go (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pure&lt;/span&gt;&lt;span&gt; a) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span&gt;    go (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Ap&lt;/span&gt;&lt;span&gt; a b) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; go a &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;++&lt;/span&gt;&lt;span&gt; go b&lt;/span&gt;
&lt;span&gt;    go (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span&gt; name) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;
&lt;span&gt;      printf &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;lt;input type=\&amp;quot;text\&amp;quot; name=%s&amp;gt;&amp;lt;br&amp;gt;&amp;quot;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;show&lt;/span&gt;&lt;span&gt; name)&lt;/span&gt;
&lt;span&gt;    go (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Checkbox&lt;/span&gt;&lt;span&gt; name) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;
&lt;span&gt;      printf &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;lt;input type=&amp;quot;&lt;/span&gt;&lt;span&gt;checkbox&lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot; name=%s&amp;gt;&amp;lt;br&amp;gt;&amp;quot;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;show&lt;/span&gt;&lt;span&gt; name)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&#34;evaluating-a-form&#34;&gt;Evaluating a form&lt;/h3&gt;
&lt;p&gt;If you have key–value associations from a POST query, you can also easily evaluate a form:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;evalForm ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Map&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Text&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;evalForm kv &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; go&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;    go (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Pure&lt;/span&gt;&lt;span&gt; a) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;span&gt;    go (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Ap&lt;/span&gt;&lt;span&gt; a b) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; (go a) &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; (go b)&lt;/span&gt;
&lt;span&gt;    go (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TextField&lt;/span&gt;&lt;span&gt; name) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;
&lt;span&gt;      fromMaybe &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span&gt; (M.lookup name kv)&lt;/span&gt;
&lt;span&gt;    go (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Checkbox&lt;/span&gt;&lt;span&gt; name) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;
&lt;span&gt;      M.lookup name kv &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Just&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;on&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For simplicity I&amp;#39;m not going to add any kind of error handling, validation, etc. We could easily add validation by introducing another constructor:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Validate&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; (b &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Either&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Text&lt;/span&gt;&lt;span&gt; a) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Form&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is similar to what &lt;code&gt;digestive-functors&lt;/code&gt; does.&lt;/p&gt;
&lt;h2 id=&#34;using-digestivefunctors&#34;&gt;Using &lt;code&gt;digestive-functors&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Now that you (maybe) understand the idea behind &lt;code&gt;digestive-functors&lt;/code&gt;, let&amp;#39;s see how to use the actual library. There are three main types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;type Form v m a&lt;/code&gt; – a form that can be rendered or evaluated.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;v&lt;/code&gt; is the type for rendered things – e.g. &lt;code style=&#34;white-space: nowrap&#34;&gt;Text&lt;/code&gt;, &lt;code style=&#34;white-space: nowrap&#34;&gt;String&lt;/code&gt;, &lt;code style=&#34;white-space: nowrap&#34;&gt;Html&lt;/code&gt;, or your own custom type. It&amp;#39;s used for validation errors, for combobox items, etc&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;m&lt;/code&gt; is the monad in which validation happens – can be &lt;code style=&#34;white-space: nowrap&#34;&gt;Identity&lt;/code&gt; if all your validation is pure, can be something &lt;code style=&#34;white-space: nowrap&#34;&gt;IO&lt;/code&gt;-like if you want to e.g. access a DB during validation)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;a&lt;/code&gt; is the type that will be returned during form evaluation – in many cases it&amp;#39;s going to be something that can be trivially constructed from the fields contained in the form&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;type Formlet v m a = Maybe a -&amp;gt; Form v m a&lt;/code&gt; – simply a function which can be passed &lt;code style=&#34;white-space: nowrap&#34;&gt;Nothing&lt;/code&gt; if you want to get a form, or &lt;code style=&#34;white-space: nowrap&#34;&gt;Just&lt;/code&gt; if you want to convert a value into form fields (i.e. do the opposite thing to evaluating a form). It is most commonly used to set default values for form fields. As far as I understand, you&amp;#39;re not really supposed to create &lt;code style=&#34;white-space: nowrap&#34;&gt;Formlet&lt;/code&gt;s of your own. Basic primitives provided by &lt;code&gt;digestive-functors&lt;/code&gt; are all either &lt;code style=&#34;white-space: nowrap&#34;&gt;Formlet&lt;/code&gt;s or something close in shape to them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;View v&lt;/code&gt; is a form that you are supposed to render after the &lt;code style=&#34;white-space: nowrap&#34;&gt;POST&lt;/code&gt; query if something went wrong. It consists of a &lt;code style=&#34;white-space: nowrap&#34;&gt;Form v m a&lt;/code&gt;, user&amp;#39;s input from the previous time they tried to submit the form, and validation errors (that should be displayed to the user when you re-render the form).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are some examples of simple forms (which can be combined with &lt;code style=&#34;white-space: nowrap&#34;&gt;&amp;lt;$&amp;gt;&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;&amp;lt;*&amp;gt;&lt;/code&gt;, and have names attached to them with &lt;code style=&#34;white-space: nowrap&#34;&gt;.:&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;textInput &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; text &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Nothing&lt;/span&gt;

&lt;span&gt;intInput &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; stringRead &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;Expected an int&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Nothing&lt;/span&gt;

&lt;span class=&#34;co&#34;&gt;-- pears shall be the default because I like them more&lt;/span&gt;
&lt;span&gt;fruitInput &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; choice [(&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;Apple&amp;quot;&lt;/span&gt;&lt;span&gt;), (&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;Pear&amp;quot;&lt;/span&gt;&lt;span&gt;)] (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Just&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you simply want to apply a function to form&amp;#39;s output, you can use
&lt;code style=&#34;white-space: nowrap&#34;&gt;&amp;lt;$&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;cutInput &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;take&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;10&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span&gt; text &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can also use &lt;code&gt;check/checkM&lt;/code&gt; to do validation, and &lt;code&gt;validate/validateM&lt;/code&gt; to do transformations that can fail.&lt;/p&gt;
&lt;p&gt;Once you have a form, you need to convert it into a &lt;code style=&#34;white-space: nowrap&#34;&gt;View&lt;/code&gt; and then render it. &lt;code&gt;digestive-functors&lt;/code&gt; doesn&amp;#39;t do any rendering for you, but it provides two helper functions in &lt;code&gt;Text.Digestive.View&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;getForm&lt;/code&gt; converts a form into a &lt;code style=&#34;white-space: nowrap&#34;&gt;View&lt;/code&gt; without any input or error message&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;postForm&lt;/code&gt; accepts a form and a function for getting form fields from the request (of type &lt;code&gt;Path -&amp;gt; m [FormInput]&lt;/code&gt;), fills the form, and gives you a &lt;code style=&#34;white-space: nowrap&#34;&gt;View&lt;/code&gt; with input and error messages and the result value of the form (if it was evaluated successfully)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You are supposed to render the &lt;code style=&#34;white-space: nowrap&#34;&gt;View&lt;/code&gt; by yourself – the &lt;a href=&#34;https://github.com/jaspervdj/digestive-functors/blob/master/examples/tutorial.lhs&#34;&gt;official tutorial&lt;/a&gt; provides an adequate example of doing that. Also, you don&amp;#39;t actually have to use &lt;code style=&#34;white-space: nowrap&#34;&gt;getForm&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;postForm&lt;/code&gt; – the &lt;a href=&#34;https://hackage.haskell.org/package/Spock-digestive&#34;&gt;&lt;code&gt;Spock-digestive&lt;/code&gt;&lt;/a&gt; package by the author of Spock abstracts that away. Here&amp;#39;s an example:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;loginAction ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;SpockAction&lt;/span&gt;&lt;span&gt; conn &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Session&lt;/span&gt;&lt;span&gt; st ()&lt;/span&gt;
&lt;span&gt;loginAction &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;let&lt;/span&gt;&lt;span&gt; formView &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; F.renderForm loginFormSpec&lt;/span&gt;
&lt;span&gt;    f &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; F.runForm &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;loginForm&amp;quot;&lt;/span&gt;&lt;span&gt; loginForm&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;case&lt;/span&gt;&lt;span&gt; f &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;of&lt;/span&gt;
&lt;span&gt;      (view, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Nothing&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;
&lt;span&gt;          site &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; formView view&lt;/span&gt;
&lt;span&gt;      (view, &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Just&lt;/span&gt;&lt;span&gt; loginReq) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;
&lt;span&gt;          &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;if&lt;/span&gt;&lt;span&gt; lrUser loginReq &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;admin&amp;quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span&gt;             lrPassword loginReq &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;123&amp;quot;&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;co&#34;&gt;-- hardcoded, yeah&lt;/span&gt;
&lt;span&gt;          &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;then&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;              sessionRegenerateId&lt;/span&gt;
&lt;span&gt;              writeSession (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Just&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; lrUser loginReq)&lt;/span&gt;
&lt;span&gt;              redirect &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;/member-area&amp;quot;&lt;/span&gt;
&lt;span&gt;          &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;else&lt;/span&gt;&lt;span&gt; site &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;              H.alertBox &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;H.BootAlertDanger&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;Login failed. Try again.&amp;quot;&lt;/span&gt;
&lt;span&gt;              formView view&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;runForm&lt;/code&gt; automatically checks whether it was a GET or POST request (and parses the request and fills the form if it was a POST).&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-12-06-digestive-functors"/></entry><entry><id>2017-12-06-stack-caching</id><title type="html">Dependencies installed by Stack aren&amp;#39;t being cached
</title><updated>2017-12-06T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-12-06-stack-caching&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random1.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I&amp;#39;ll start off with a fiddly build question. We&amp;#39;ve been using CircleCI, and are trying to sort out caching of the Stack build state. However despite what looks like a correct caching and restore of &lt;code&gt;.stack-work&lt;/code&gt;, we&amp;#39;re not seeing any actual caching.&lt;/p&gt;
&lt;p&gt;On a build with no source changes we get:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;foo-1.0.0: unregistering (missing dependencies: foo-util)
foo-lib-1.0.0: unregistering (missing dependencies: foo-test, foo-util)
foo-test-1.0.0: unregistering (missing dependencies: foo-util)
foo-util-1.0.0: unregistering (local file changes: util/Foo/Orange.hs
    util/Foo/Pear.hs util/Foo/Apple.hs util/Foo/Banana.hs util/...)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&amp;#39;m not sure if we&amp;#39;re doing something silly and missing something to cache, or if cache save/restore doesn&amp;#39;t actually work yet, or if stack is doing something odd.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Can you send your &lt;code style=&#34;white-space: nowrap&#34;&gt;circle.yml&lt;/code&gt; config?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random1.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Sure, here it is:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;&lt;span class=&#34;fu&#34;&gt;version&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;
&lt;span class=&#34;fu&#34;&gt;jobs&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;build_and_test&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;co&#34;&gt;                         # NB. some parts omitted&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; checkout&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;restore_cache&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; ...&lt;/span&gt;&lt;span class=&#34;co&#34;&gt;                # omitted&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; stack_build&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;command&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; stack build --test&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;deploy&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; ...&lt;/span&gt;&lt;span class=&#34;co&#34;&gt;                       # omitted&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;save_cache&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; dependency-cache-{{ .Branch }}-{{arch}}-{{ .Revision }}&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;paths&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;.stack-work&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Okay, so just to make sure: there&amp;#39;s no problem with snapshot deps (from &lt;code style=&#34;white-space: nowrap&#34;&gt;.stack&lt;/code&gt;), but caching/restoring of &lt;code&gt;.stack-work&lt;/code&gt; doesn&amp;#39;t work?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random1.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;It looks like it partially works. &lt;code style=&#34;white-space: nowrap&#34;&gt;extra-deps&lt;/code&gt; are cached fine but it always rebuilds our code from scratch.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Oh, I figured it out: apparently Stack creates &lt;code&gt;.stack-work&lt;/code&gt; folders in subprojects as well, so you have to cache them too:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;save_cache&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;paths&lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;:&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; .stack-work&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; lib/.stack-work&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; util/.stack-work&lt;/span&gt;
&lt;span class=&#34;at&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;at&#34;&gt; test/.stack-work&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Also, I asked authors of Stack and apparently currently it&amp;#39;s not possible to ask Stack to consolidate &lt;code&gt;.stack-work&lt;/code&gt;s into one directory, so if you decide to look for a way to do that you should probably redecide :P&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random1.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Final update: got everything working! Still running tests even without compiling, but drops our noop builds from 13m to 1m.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-12-06-stack-caching"/></entry><entry><id>2017-12-02-functor-laws-and-optimization</id><title type="html">Does GHC apply functor laws during optimization?
</title><updated>2017-12-02T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-12-02-functor-laws-and-optimization&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;[...] Totally different question, out of curiosity: does GHC apply functor laws in optimization?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;div class=&#34;thumbnail thumbnail-right thumbnail-code&#34;&gt;&lt;a href=&#34;https://hackage.haskell.org/package/base-4.10.1.0/docs/src/Control.Category.html#line-40&#34;&gt;&lt;img src=&#34;https://monadfix.com/thumbnails/category-rules.png&#34; srcset=&#34;https://monadfix.com/thumbnails/2x_category-rules.png 2x&#34;&gt;&lt;/a&gt;&lt;p class=&#34;thumbnail-caption&#34;&gt;Rewrite rules defined in &lt;code&gt;Control.Category&lt;/code&gt;
&lt;/p&gt;&lt;/div&gt;&lt;p&gt;AFAIK, no. Some rules related to &lt;code style=&#34;white-space: nowrap&#34;&gt;Arrow&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;Category&lt;/code&gt; are applied, and there are lots of rules for lists and some other stuff, but I&amp;#39;ve never seen &lt;code style=&#34;white-space: nowrap&#34;&gt;Monad&lt;/code&gt;/&lt;code style=&#34;white-space: nowrap&#34;&gt;Functor&lt;/code&gt; laws used in optimizations.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ll grep through the sources of &lt;code style=&#34;white-space: nowrap&#34;&gt;base&lt;/code&gt; to be sure.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Haha, that&amp;#39;s one way to solve it.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;The previous time I had this question, I didn&amp;#39;t find anything :P&lt;/p&gt;
&lt;p&gt;Yeah, apparently no &lt;code style=&#34;white-space: nowrap&#34;&gt;Functor&lt;/code&gt;-related rules. Of course, GHC could have hard-wired &lt;code style=&#34;white-space: nowrap&#34;&gt;Functor&lt;/code&gt;/&lt;code style=&#34;white-space: nowrap&#34;&gt;Monad&lt;/code&gt;-related optimizations, but I remember asking someone knowledgeable about that and I got told there was no such thing built-in.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I wonder how much faster Haskell code would be if it were safe to apply such optimizations.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;There was a &lt;a href=&#34;https://ghc.haskell.org/trac/ghc/ticket/8767&#34;&gt;Trac ticket&lt;/a&gt; about it. There&amp;#39;s a good discussion in the comments.&lt;/p&gt;
&lt;p&gt;The issue is that there are unlawful &lt;code style=&#34;white-space: nowrap&#34;&gt;Functor&lt;/code&gt; instances out there and optimizations shouldn&amp;#39;t break them.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Ahhh, they can add the rules themselves.&lt;/p&gt;
&lt;p&gt;That really is a good solution. That puts the onus on library authors to prove correctness before benefiting but doesn&amp;#39;t punish code for breaking the laws.&lt;/p&gt;
&lt;p&gt;But I wonder why the rules are not written for the functors in &lt;code style=&#34;white-space: nowrap&#34;&gt;base&lt;/code&gt; – maybe the rules are in terms of the monomorphic functions instead of &lt;code style=&#34;white-space: nowrap&#34;&gt;fmap&lt;/code&gt;?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;There are rules for monomorphic functions, such as &lt;code style=&#34;white-space: nowrap&#34;&gt;map&lt;/code&gt;, but you don&amp;#39;t get these rules applied in a polymorphic setting.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Not even if &lt;code style=&#34;white-space: nowrap&#34;&gt;map&lt;/code&gt; got inlined in place of &lt;code style=&#34;white-space: nowrap&#34;&gt;fmap&lt;/code&gt;?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;That&amp;#39;s not polymorphic anymore.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-12-02-functor-laws-and-optimization"/></entry><entry><id>2017-12-02-ghc-inlining</id><title type="html">When does GHC inline?
</title><updated>2017-12-02T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-12-02-ghc-inlining&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;When does GHC inline? I just wrote a tiny function that is merely for convenience to convert things. It really could / should be inlined. Do I need to tell GHC this?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;If a function is small and non-recursive GHC will inline it.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Even across module boundaries?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Yes, it puts an optimized version of the function into interface files (&lt;code style=&#34;white-space: nowrap&#34;&gt;.hi&lt;/code&gt;) and inlines across modules.&lt;/p&gt;
&lt;p&gt;If you add an &lt;code&gt;{-# INLINE #-}&lt;/code&gt; pragma it will put an unoptimized version of the function into the &lt;code style=&#34;white-space: nowrap&#34;&gt;.hi&lt;/code&gt; file, so you&amp;#39;d want to avoid specifying this pragma unless you need to inline the function body verbatim and optimize at each use site (as opposed to optimizing at definition site).&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Ahh, yes that makes great sense, I can see how some cases would optimize much better at call site instead.&lt;/p&gt;
&lt;p&gt;But even functions optimized at definition site can still be inlined at call site, correct?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Yes, if they are small and non-recursive.&lt;/p&gt;
&lt;p&gt;It also puts a toll on compile times if you use &lt;code style=&#34;white-space: nowrap&#34;&gt;INLINE&lt;/code&gt; too much, because optimizing at use site means optimizing multiple times.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-12-02-ghc-inlining"/></entry><entry><id>2017-11-15-speeding-up-th-in-ghcjs</id><title type="html">Speeding up Template Haskell in GHCJS
</title><updated>2017-11-15T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-11-15-speeding-up-th-in-ghcjs&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;[...] I&amp;#39;m using GHCJS and TH makes it go amazingly slow. [...]&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2018-03-07:&lt;/strong&gt; apparently, this has been fixed in GHCJS at some point in the past and now the trick described below &lt;strong&gt;doesn&amp;#39;t result in any speedup&lt;/strong&gt; at all (e.g. it brings no speedup on ghcjs-0.2.0.9006020_ghc-7.10.3, which is fairly old already).&lt;/p&gt;
&lt;p&gt;Thanks to Niklas Hambüchen for &lt;a href=&#34;https://www.reddit.com/r/haskell/comments/824zn6/dirt_cheap_haskell_publishing_our_answers_to_our/dvb1zrp/&#34;&gt;pointing this out&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;There&amp;#39;s a trick to speed up TH in GHCJS: make it go in one pass. Instead of:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Foo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;makeLenses &amp;#39;&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Foo&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;makeLenses &amp;#39;&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Bar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;try putting everything into one splice:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Foo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;  decs1 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; makeLenses &amp;#39;&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Foo&lt;/span&gt;
&lt;span&gt;  decs2 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; makeLenses &amp;#39;&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Bar&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; decs1 &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;++&lt;/span&gt;&lt;span&gt; decs2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or with &lt;code style=&#34;white-space: nowrap&#34;&gt;sequenceA&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;fu&#34;&gt;concat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;traverse&lt;/span&gt;&lt;span&gt; makeLenses [ &amp;#39;&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Foo&lt;/span&gt;&lt;span&gt;, &amp;#39;&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Bar&lt;/span&gt;&lt;span&gt; ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is faster because GHCJS starts a Node.js process for each splice. A single splice requires less overhead.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Wow that is an amazing trick! You may have just cut down my build times by a large factor!&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-11-15-speeding-up-th-in-ghcjs"/></entry><entry><id>2017-11-14-records</id><title type="html">Dealing with records in Haskell
</title><updated>2017-11-14T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-11-14-records&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;How do you guys deal with records? I really like lenses, but I don&amp;#39;t really like Template Haskell and &lt;code style=&#34;white-space: nowrap&#34;&gt;makeLenses&lt;/code&gt;. I really like &lt;a href=&#34;https://hackage.haskell.org/package/generic-lens&#34;&gt;&lt;code&gt;generic-lens&lt;/code&gt;&lt;/a&gt;, but the syntax is so verbose:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;record &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;^.&lt;/span&gt;&lt;span&gt; field &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;fieldname&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then I still have the problem with record field names colliding.&lt;/p&gt;
&lt;p&gt;Also, I&amp;#39;d love to just get rid of the record field accessors that get created for records. But then I can&amp;#39;t construct a record because lenses don&amp;#39;t let you construct new records from nothing. I&amp;#39;ve tried deriving &lt;code style=&#34;white-space: nowrap&#34;&gt;Default&lt;/code&gt;... but that&amp;#39;s not ideal and in some cases just downright bad. I can imagine a version of &lt;code&gt;generic-lens&lt;/code&gt;&amp;#39;s &lt;code style=&#34;white-space: nowrap&#34;&gt;field&lt;/code&gt; function that allows you to de-mangle the record field name in some way.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;You can go about it like this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;declareFields [d|&lt;/span&gt;
&lt;span&gt;  data Person = Person {&lt;/span&gt;
&lt;span&gt;    _personName :: Text,&lt;/span&gt;
&lt;span&gt;    _personAge  :: Int }&lt;/span&gt;
&lt;span&gt;|]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This gives you lenses called &lt;code style=&#34;white-space: nowrap&#34;&gt;name&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;age&lt;/code&gt;. Names can be duplicated (the lenses are polymorphic), and the actual generated type is not a record so accessors like &lt;code&gt;_personName&lt;/code&gt; don&amp;#39;t get generated.&lt;/p&gt;
&lt;p&gt;If all fields in such a structure are lazy (i.e. without the bangs), you can construct a record with lenses like this (I wouldn&amp;#39;t recommend this approach though because if you forget one field the compiler won&amp;#39;t warn you):&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;bob ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Person&lt;/span&gt;
&lt;span&gt;bob &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;undefined&lt;/span&gt;
&lt;span&gt;        &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; name &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.~&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;st&#34;&gt;&amp;quot;Bob&amp;quot;&lt;/span&gt;
&lt;span&gt;        &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; age  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.~&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;24&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To be honest, in my experience constructing records from scratch doesn&amp;#39;t happen that often so I don&amp;#39;t see “you have to use &lt;code&gt;_personName&lt;/code&gt; once in a while” as a problem and just use &lt;code style=&#34;white-space: nowrap&#34;&gt;makeFields&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;If you have a sensible default or some smart constructor then yeah.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Well, if you have a sensible default it&amp;#39;s even better but this doesn&amp;#39;t seem that bad either:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;fu&#34;&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Person&lt;/span&gt;
&lt;span&gt;  { _personName &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;  , _personAge  &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;  }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;It&amp;#39;s only bad when &lt;code style=&#34;white-space: nowrap&#34;&gt;Person&lt;/code&gt; is &lt;code&gt;AppDbContextHandle&lt;/code&gt; and you have &lt;code&gt;_appDbContextHandleName&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Ah, in this case just go the “abbreviate all the things” route :) We do it at work:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;AppDbContextHandle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;AppDbContextHandle&lt;/span&gt;
&lt;span&gt;  { _adchFoo &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;  , _adchBar &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;  }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Though if you hate it I could write a Template Haskell helper for you that lets you write things like this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;construct [&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;let&lt;/span&gt;&lt;span&gt; field1 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;      field2 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;AppDbContextHandle&lt;/span&gt;
&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I&amp;#39;m using &lt;a href=&#34;http://travis.athougies.net/projects/beam.html&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;beam&lt;/code&gt;&lt;/a&gt; which doesn&amp;#39;t support &lt;code style=&#34;white-space: nowrap&#34;&gt;makeFields&lt;/code&gt; so I have to use &lt;code style=&#34;white-space: nowrap&#34;&gt;makeLenses&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The solution with the helper would indeed be nice. However I&amp;#39;m also using GHCJS and TH makes it go amazingly slow. On the other hand, that&amp;#39;s not a huge deal because I rarely build the app in GHCJS. So many constraints...&lt;/p&gt;
&lt;p&gt;Which is why I like &lt;code&gt;generic-lens&lt;/code&gt; so much. No TH (so no slowness) and it obviously works fine with &lt;code style=&#34;white-space: nowrap&#34;&gt;beam&lt;/code&gt; since it&amp;#39;s just deriving from &lt;code style=&#34;white-space: nowrap&#34;&gt;Generic&lt;/code&gt;. But I&amp;#39;d need to use &lt;code style=&#34;white-space: nowrap&#34;&gt;-XOverloadedRecordFields&lt;/code&gt; or something.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;By the way, there&amp;#39;s another solution that uses new &lt;code style=&#34;white-space: nowrap&#34;&gt;-XOverloadedLabels&lt;/code&gt;: &lt;a href=&#34;https://hackage.haskell.org/package/overloaded-records&#34;&gt;&lt;code&gt;overloaded-records&lt;/code&gt;&lt;/a&gt;. You define a record as usual, and then call &lt;code&gt;overloadedRecord&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Data.Default&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Default&lt;/span&gt;&lt;span&gt;(def))&lt;/span&gt;
&lt;span class=&#34;kw&#34;&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Data.OverloadedRecords.TH&lt;/span&gt;&lt;span&gt; (overloadedRecord)&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;newtype&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bar&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bar&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; _bar ::&lt;/span&gt;&lt;span&gt; a }&lt;/span&gt;

&lt;span&gt;overloadedRecord def &amp;#39;&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Bar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then you&amp;#39;ll be able to use overloaded labels as lenses for &lt;code style=&#34;white-space: nowrap&#34;&gt;Bar&lt;/code&gt;&amp;#39;s fields without even having to import anything:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE OverloadedLabels #-}&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Control.Lens&lt;/span&gt;&lt;span&gt; ((+~))&lt;/span&gt;

&lt;span class=&#34;ot&#34;&gt;add ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Bar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;
&lt;span&gt;add n &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;#&lt;/span&gt;&lt;span&gt;bar &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;+~&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(I suspect there are some caveats though.)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Possibly performance. &lt;code&gt;generic-lens&lt;/code&gt; has no performance penalty, but I&amp;#39;m not sure about this library. As far as I know &lt;code&gt;generic-lens&lt;/code&gt; has gone through a lot of effort to ensure that it does not impose runtime overhead. Take a look at &lt;code&gt;generic-lens&lt;/code&gt;&amp;#39;s use of &lt;a href=&#34;https://hackage.haskell.org/package/inspection-testing&#34;&gt;&lt;code&gt;inspection-testing&lt;/code&gt;&lt;/a&gt;. They “prove” that GHC generates the same lenses that you&amp;#39;d write by hand.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;This sounds cool. Although I think they couldn&amp;#39;t prove that GHC manages to do that in every case, especially if optimizations kick in a different order (i.e. the lens is inlined first, then its part moved around, etc). &lt;code&gt;inspection-testing&lt;/code&gt; checks the generated Core, but of course it can only check what you pass to it, and GHC might generate different Core in different circumstances.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I think I&amp;#39;m in love with the overloaded labels approach to &lt;code&gt;generic-lens&lt;/code&gt; described in &lt;a href=&#34;https://twitter.com/eacameron88/status/930819236209012736&#34;&gt;this tweet&lt;/a&gt;. It uses &lt;a href=&#34;https://hackage.haskell.org/package/generic-lens-labels&#34;&gt;&lt;code&gt;generic-lens-labels&lt;/code&gt;&lt;/a&gt;. With &lt;code style=&#34;white-space: nowrap&#34;&gt;-XDuplicateRecordFields&lt;/code&gt; you can allow the ambiguity which only matters in record updates anyway. But if the only time you use that is to create a new record, then there&amp;#39;s no ambiguity.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;The only issue I have with overloaded labels is that different libraries have different use cases for them, and those may conflict.&lt;/p&gt;
&lt;p&gt;For instance, &lt;a href=&#34;https://hackage.haskell.org/package/haskell-gi&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;haskell-gi&lt;/code&gt;&lt;/a&gt; uses them for FFI fields. Does it conflict with use of overloaded labels as lenses?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Interesting. Yeah, I don&amp;#39;t know. I use records so heavily that I&amp;#39;d be willing to sacrifice pretty much every other use though. ;)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2018-03-06:&lt;/strong&gt; it wasn&amp;#39;t mentioned in the original dialogue, but look at the &lt;a href=&#34;http://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#duplicate-record-fields&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;-XDuplicateRecordFields&lt;/code&gt;&lt;/a&gt; extension which got introduced in GHC 8.0. It, too, makes working with records easier in Haskell.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-11-14-records"/></entry><entry><id>2017-11-09-generics-intro</id><title type="html">“Where to start with generics?”
</title><updated>2017-11-09T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-11-09-generics-intro&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Hi! I would like to do some things with generics but have no idea where to start.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I think the best starting point for understanding generics is understanding the algebra of types. Check out this article series: &lt;a href=&#34;http://chris-taylor.github.io/blog/2013/02/10/the-algebra-of-algebraic-data-types/&#34;&gt;The Algebra of Algebraic Data Types&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you&amp;#39;re comfortable with thinking about all types as sums and products, you already understand the bulk of generic programming.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/3noch&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/3noch.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Elliot Cameron&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Awesome! I&amp;#39;ll start there. I find records particularly annoying to work with and things like &lt;a href=&#34;https://hackage.haskell.org/package/generic-lens&#34;&gt;&lt;code&gt;generic-lens&lt;/code&gt;&lt;/a&gt; give me hope, but that and similar tools are still a bit too inflexible so I hope to customize them a bit.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;If you&amp;#39;re particularly curious about generics, I would also recommend reading Andres Löh&amp;#39;s &lt;a href=&#34;https://raw.githubusercontent.com/kosmikus/SSGEP/master/LectureNotes.pdf&#34;&gt;lecture notes on modern generics&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You don&amp;#39;t really need it if you just want to use generics but if you&amp;#39;ve already heard about a bunch of concepts (GADTs, type-indexed lists, etc) without being especially familiar with them, it makes for nice bedtime reading &lt;em&gt;and&lt;/em&gt; tricks you into understanding the &lt;a href=&#34;https://hackage.haskell.org/package/generics-sop&#34;&gt;&lt;code&gt;generics-sop&lt;/code&gt;&lt;/a&gt; library along the way.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-11-09-generics-intro"/></entry><entry><id>2017-11-02-editor-integration</id><title type="html">Haskell integration with editors
</title><updated>2017-11-02T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-11-02-editor-integration&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random5.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Do any non-Vim/Emacs editors have good Haskell integration?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I would go as far as to say that there&amp;#39;s no good editor integration for Haskell at all. There&amp;#39;s &lt;code style=&#34;white-space: nowrap&#34;&gt;ghc-mod&lt;/code&gt; and the ecosystem around it, but it stops being usable as soon as the project is big enough. It&amp;#39;s just too slow. And lots of Haskell tooling suffers from the issue that there&amp;#39;s no good package with the Haskell AST (there&amp;#39;s &lt;a href=&#34;https://hackage.haskell.org/package/haskell-src-exts&#34;&gt;&lt;code&gt;haskell-src-exts&lt;/code&gt;&lt;/a&gt;, but it&amp;#39;s just not what the compiler uses, and the discrepancies are often noticeable). Another story is integration with build systems... Honestly, at one point I gave up and decided not to use Haskell tooling, it&amp;#39;s broken.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/alanz&#34;&gt;@alanz&lt;/a&gt; is doing an immense amount of work to fix that.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;NB: I heard from a coworker that Sublime can be set up to work as well as Emacs; if you consider Emacs&amp;#39;s integration good, I could ask him for details about his Sublime setup if you&amp;#39;re interested.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2018-03-05:&lt;/strong&gt; the coworker adds that Atom&amp;#39;s integration is better than Sublime&amp;#39;s, but also that Atom is too slow :/ Also take a look at &lt;a href=&#34;https://github.com/rainbyte/haskell-ide-chart&#34;&gt;this chart&lt;/a&gt; of Haskell support in various IDEs and editors.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;div class=&#34;thumbnail thumbnail-right thumbnail-page&#34;&gt;&lt;a href=&#34;https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/trees-that-grow.pdf&#34;&gt;&lt;img src=&#34;https://monadfix.com/thumbnails/trees-that-grow.png&#34; srcset=&#34;https://monadfix.com/thumbnails/2x_trees-that-grow.png 2x&#34;&gt;&lt;/a&gt;&lt;p class=&#34;thumbnail-caption&#34;&gt;Trees That Grow (Najd 2016)
&lt;/p&gt;&lt;/div&gt;&lt;p&gt;There were discussions in the GHC mailing list about defining an external AST for GHC which could be used by various tooling. They also plan to apply the principles from the &lt;a href=&#34;https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/trees-that-grow.pdf&#34;&gt;“Trees That Grow” paper&lt;/a&gt;, which is an amazing idea. All of it is happening right now, and Haskell will get the tooling it deserves sooner or later (but, sadly, &amp;quot;later&amp;quot; sounds more realistic).&lt;/p&gt;
&lt;p&gt;Anyway, I&amp;#39;d still recommend &lt;a href=&#34;https://hackage.haskell.org/package/hasktags&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;hasktags&lt;/code&gt;&lt;/a&gt; to generate tags. Although it doesn&amp;#39;t work very good either (sometimes it misses some definitions, sometimes it indexes non-definitions), but it works 90% of the time and “Jump to definition” is just something that gives an immense productivity boost (even if a bit broken).&lt;/p&gt;
&lt;p&gt;One important caveat is that you can&amp;#39;t jump to definitions generated by Template Haskell. That&amp;#39;s quite obvious in retrospect, because &lt;code style=&#34;white-space: nowrap&#34;&gt;hasktags&lt;/code&gt; doesn&amp;#39;t run the compile-time code, but might be a bit disappointing when you can&amp;#39;t jump to a lens generated by &lt;code style=&#34;white-space: nowrap&#34;&gt;makeLenses&lt;/code&gt; or something like that.&lt;/p&gt;
&lt;p&gt;And if you use Stack as your build tool, just having &lt;code&gt;stack build --file-watch&lt;/code&gt; in a terminal window next to the editor is often sufficient.&lt;/p&gt;
&lt;div class=&#34;thumbnail thumbnail-left thumbnail-gif&#34;&gt;&lt;a href=&#34;https://github.com/haskell/haskell-ide-engine&#34;&gt;&lt;img src=&#34;https://monadfix.com/thumbnails/haskell-ide-engine.gif&#34; srcset=&#34;https://monadfix.com/thumbnails/2x_haskell-ide-engine.gif 2x&#34;&gt;&lt;/a&gt;&lt;p class=&#34;thumbnail-caption&#34;&gt;Autocompletion done with &lt;code&gt;haskell-ide-engine&lt;/code&gt;
&lt;/p&gt;&lt;/div&gt;&lt;p&gt;Most of the people who worked on tooling such as &lt;code&gt;haskell-mode&lt;/code&gt;, &lt;code style=&#34;white-space: nowrap&#34;&gt;ghc-mod&lt;/code&gt;, and &lt;code&gt;ide-backend&lt;/code&gt;, decided to consolidate their efforts and work on &lt;a href=&#34;https://github.com/haskell/haskell-ide-engine&#34;&gt;&lt;code&gt;haskell-ide-engine&lt;/code&gt;&lt;/a&gt;. What&amp;#39;s exciting about this is that they plan to support &lt;a href=&#34;https://microsoft.github.io/language-server-protocol/&#34;&gt;Language Server Protocol&lt;/a&gt;. Basically, this means that we&amp;#39;ll get Haskell support in all editors that support LSP, so it&amp;#39;s going to be N+M rather than N×M.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random5.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Ok cool, I’ll try out &lt;code style=&#34;white-space: nowrap&#34;&gt;hasktags&lt;/code&gt; tomorrow. I’ll also try &lt;code&gt;haskell-ide-engine&lt;/code&gt; with VS Code tomorrow, looks like that’s working?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Things are working up until they break, which might be when (1) the project is too big and the tooling gets painfully slow to use, (2) you need an obscure language extension that wreaks havoc on the tooling.&lt;/p&gt;
&lt;p&gt;Especially if it&amp;#39;s an extension implemented in the latest compiler version and it&amp;#39;s a syntactic addition. When &lt;code style=&#34;white-space: nowrap&#34;&gt;-XLambdaCase&lt;/code&gt; was introduced, everything &lt;code&gt;haskell-src-exts&lt;/code&gt;-based just stopped working – that&amp;#39;s just one example.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2018-03-05:&lt;/strong&gt; I&amp;#39;ve been &lt;a href=&#34;https://www.reddit.com/r/haskell/comments/824zn6/dirt_cheap_haskell_publishing_our_answers_to_our/dv8890e/&#34;&gt;told&lt;/a&gt; on Reddit that &lt;a href=&#34;https://hackage.haskell.org/package/fast-tags&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;fast-tags&lt;/code&gt;&lt;/a&gt; is faster, more accurate than &lt;code style=&#34;white-space: nowrap&#34;&gt;hasktags&lt;/code&gt;, can work incrementally, and supports qualified identifiers. I haven&amp;#39;t tried it myself yet, but it sounds cool.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-11-02-editor-integration"/></entry><entry><id>2017-11-02-monad-transformers</id><title type="html">Briefly about monad transformers
</title><updated>2017-11-02T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-11-02-monad-transformers&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random5.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I&amp;#39;ve got a kinda generic question. How do monad transformers work?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Well, the reason to use monad transformers is to get the &lt;code style=&#34;white-space: nowrap&#34;&gt;Monad&lt;/code&gt; instances automatically. For example, there&amp;#39;s no runtime difference between &lt;code style=&#34;white-space: nowrap&#34;&gt;a -&amp;gt; IO b&lt;/code&gt; and &lt;code&gt;ReaderT a IO b&lt;/code&gt;, but the latter has a &lt;code style=&#34;white-space: nowrap&#34;&gt;Monad&lt;/code&gt; instance, whereas the former doesn&amp;#39;t. Actually, that&amp;#39;s it.&lt;/p&gt;
&lt;p&gt;Of course, we could use a function instead:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;state &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; env &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Either&lt;/span&gt;&lt;span&gt; exc (a, state))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But we want a &lt;code style=&#34;white-space: nowrap&#34;&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt; that does all the plumbing, and to get this we express the same thing as a transformers stack:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;dt&#34;&gt;StateT&lt;/span&gt;&lt;span&gt; state (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ReaderT&lt;/span&gt;&lt;span&gt; env (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExceptT&lt;/span&gt;&lt;span&gt; exc &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt;)) a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random5.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Ok, that makes sense.&lt;/p&gt;
&lt;p&gt;I’ll read that chapter of @bitemyapp’s book on that and ask you if I have any specific questions.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;And we couldn&amp;#39;t define a &lt;code style=&#34;white-space: nowrap&#34;&gt;Monad&lt;/code&gt; instance for &lt;code style=&#34;white-space: nowrap&#34;&gt;a -&amp;gt; IO b&lt;/code&gt; because it&amp;#39;s unclear whether we want it to behave as &lt;code&gt;ReaderT a IO b&lt;/code&gt; or &lt;code&gt;Reader a (IO b)&lt;/code&gt;. So the structure of transformers layers tells the compiler how deep we want &lt;code style=&#34;white-space: nowrap&#34;&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt; to inspect the structure of the types.&lt;/p&gt;
&lt;p&gt;(Well, actually, &lt;code style=&#34;white-space: nowrap&#34;&gt;a -&amp;gt; IO b&lt;/code&gt; has a &lt;code style=&#34;white-space: nowrap&#34;&gt;Monad&lt;/code&gt; instance and it&amp;#39;s indeed equivalent to &lt;code&gt;Reader a (IO b)&lt;/code&gt; rather than &lt;code&gt;ReaderT a IO b&lt;/code&gt;.)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-11-02-monad-transformers"/></entry><entry><id>2017-11-02-servant-yesod</id><title type="html">Briefly on Servant vs Yesod
</title><updated>2017-11-02T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-11-02-servant-yesod&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random5.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;How does &lt;a href=&#34;http://haskell-servant.readthedocs.io/en/stable/&#34;&gt;Servant&lt;/a&gt; compare to &lt;a href=&#34;https://www.yesodweb.com&#34;&gt;Yesod&lt;/a&gt;?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;The primary philosophical difference is that Servant tries to do everything using type-level tricks, while Yesod uses Template Haskell a lot. The code looks very different with these frameworks because of that. What&amp;#39;s common between them is that they&amp;#39;re both &lt;a href=&#34;https://hackage.haskell.org/package/wai&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;wai&lt;/code&gt;&lt;/a&gt;-based, meaning they can run atop any &lt;code style=&#34;white-space: nowrap&#34;&gt;wai&lt;/code&gt;-compatible server (&lt;a href=&#34;https://hackage.haskell.org/package/warp&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;warp&lt;/code&gt;&lt;/a&gt; or &lt;a href=&#34;https://hackage.haskell.org/package/warp-tls&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;warp-tls&lt;/code&gt;&lt;/a&gt;), and that&amp;#39;s great. I recommend against frameworks that aren&amp;#39;t &lt;code style=&#34;white-space: nowrap&#34;&gt;wai&lt;/code&gt;-based (this includes Snap and Happstack) because &lt;code style=&#34;white-space: nowrap&#34;&gt;warp&lt;/code&gt; is a great web server, it&amp;#39;s performant and configurable. Now, I&amp;#39;m not going to give a point-by-point comparison for Servant and Yesod because they&amp;#39;re just so different that having such a list might be misleading. For instance, they both support type-safe routing, but it&amp;#39;s done in wildly different ways.&lt;/p&gt;
&lt;p&gt;I&amp;#39;d say it&amp;#39;s useful to know both. If you implement a web API that talks to the front-end using JSON, I recommend Servant. If you want a multi-page web-app that has user authorization and stuff like this, Yesod is the path of least resistance. And since both of them are &lt;code style=&#34;white-space: nowrap&#34;&gt;wai&lt;/code&gt;-based (did I mention it&amp;#39;s great? well, here&amp;#39;s another reason why) you can embed a Servant website as a subsite for Yesod, and vice versa, you can run a Yesod website as part of a Servant API.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random5.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I have more experience with Yesod (am a contributor, read a lot of the code) but I’m finding that I’m just ripping out most of it – so I’ll give Servant a try.&lt;/p&gt;
&lt;p&gt;I’m a little worried it looks too complex to introduce to beginners.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/int-index&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/int-index.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Vladislav Zavialov&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;It definitely is very complex on the inside, if you try to look at the definitions they&amp;#39;re monstrous – but I&amp;#39;d claim that using it isn&amp;#39;t hard at all. Those definitions are so complex precisely to allow for elegant code that uses them, they try to hide a lot of complexity.&lt;/p&gt;
&lt;p&gt;Of course, it doesn&amp;#39;t help that Haskell doesn&amp;#39;t have good facilities for type-level programming. In a language where functions are promoted and there&amp;#39;s proper relevant quantification (might be getting a bit technical here), Servant could be implemented much nicer.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-11-02-servant-yesod"/></entry><entry><id>2017-10-30-conduit-leak</id><title type="html">Fixing a memory leak in &lt;code style=&#34;white-space: nowrap&#34;&gt;conduit&lt;/code&gt; code
</title><updated>2017-10-30T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-10-30-conduit-leak&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/reactormonk&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/reactormonk.jpeg&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Simon Hafner&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;What exactly prevents this Conduit code from running in constant memory?&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/reactormonk/non-constant-memory&#34;&gt;https://github.com/reactormonk/non-constant-memory&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/neongreen&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/neongreen.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Artyom Kazak&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Roman has filed a PR with a writeup here: &lt;a href=&#34;https://github.com/reactormonk/non-constant-memory/pull/1&#34;&gt;https://github.com/reactormonk/non-constant-memory/pull/1&lt;/a&gt;. I&amp;#39;m not sure whether it&amp;#39;s enough for your purposes or not, so please reply to him if you want a deeper investigation.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/effectfully&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/effectfully.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Roman Kireev&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;&lt;em&gt;[The following is a copy of the writeup linked above.]&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My preferred way to profile Haskell programs looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;stack build --profile
stack exec -- json-unify-exe \
    +RTS -sstderr -N -K1K -A4M -n1M -qb0 -xt -hy -p
hp2ps -e8in json-unify-exe.hp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running the &lt;a href=&#34;https://github.com/reactormonk/non-constant-memory&#34;&gt;original version&lt;/a&gt; of code results in:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://user-images.githubusercontent.com/10480926/32322637-40b1643e-bfd6-11e7-9bd3-0e2b4bf620ed.png&#34; alt&gt;&lt;/p&gt;
&lt;p&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;ARR_WORDS&lt;/code&gt; is stuff related to &lt;code style=&#34;white-space: nowrap&#34;&gt;ByteString&lt;/code&gt;. So a lot of &lt;code style=&#34;white-space: nowrap&#34;&gt;ByteString&lt;/code&gt;s are loaded into memory. The culprit is &lt;code style=&#34;white-space: nowrap&#34;&gt;foldChunks&lt;/code&gt; (I cannot say right now what exactly the problem with &lt;code style=&#34;white-space: nowrap&#34;&gt;foldChunks&lt;/code&gt; is, it&amp;#39;s just my intuition said to me it looks suspicious; I&amp;#39;ll think about it), so if we remove the following code (note also that &lt;code&gt;runResourceT&lt;/code&gt; is completely redundant here)&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;allJson &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; runResourceT &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; runCConduit &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; sourceTBMChan trees&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;=$=&amp;amp;&lt;/span&gt;&lt;span&gt; foldChunks &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;100&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;=$=&amp;amp;&lt;/span&gt;&lt;span&gt; foldChunks &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;10&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;=$=&amp;amp;&lt;/span&gt;&lt;span&gt; foldChunks &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;10&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;=$=&amp;amp;&lt;/span&gt;&lt;span&gt; foldChunks &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;10&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;=$=&amp;amp;&lt;/span&gt;&lt;span&gt; foldlC (\x y &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; force &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mappend&lt;/span&gt;&lt;span&gt; x y) &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mempty&lt;/span&gt;
&lt;span&gt;Prelude.print &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; someStuff &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; unfix &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; force allJson&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and write this instead:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;allJson &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; runCConduit &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; sourceTBMChan trees&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;=$=&amp;amp;&lt;/span&gt;&lt;span&gt; foldlC (\x y &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; force &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mappend&lt;/span&gt;&lt;span&gt; x y) &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mempty&lt;/span&gt;
&lt;span&gt;Prelude.print &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; someStuff &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; unfix &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; force allJson&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;we&amp;#39;ll get:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://user-images.githubusercontent.com/10480926/32322926-4661a32a-bfd7-11e7-9162-65db0128bbe0.png&#34; alt&gt;&lt;/p&gt;
&lt;p&gt;Which is the actual leak. But it&amp;#39;s a simple one: you just allocate a lot of &lt;code style=&#34;white-space: nowrap&#34;&gt;[]&lt;/code&gt; things, i.e. lists. Namely, &lt;code style=&#34;white-space: nowrap&#34;&gt;x&lt;/code&gt; and &lt;code style=&#34;white-space: nowrap&#34;&gt;y&lt;/code&gt; in &lt;code&gt;\x y -&amp;gt; force $ mappend x y&lt;/code&gt; are of the same type: &lt;code&gt;Fix TestType&lt;/code&gt;. The &lt;code style=&#34;white-space: nowrap&#34;&gt;Monoid&lt;/code&gt; instance for this type is:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Monoid&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Fix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mappend&lt;/span&gt;&lt;span&gt; a b &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Fix&lt;/span&gt;&lt;span&gt; (unfix a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;`mappend`&lt;/span&gt;&lt;span&gt; unfix b)&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mempty&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Fix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mempty&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;which in the mappend case uses the &lt;code style=&#34;white-space: nowrap&#34;&gt;Monoid&lt;/code&gt; instance of &lt;code style=&#34;white-space: nowrap&#34;&gt;TestType&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;
&lt;span&gt;  {&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; inner ::&lt;/span&gt;&lt;span&gt; [a]&lt;/span&gt;
&lt;span&gt;  ,&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; someStuff ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Int&lt;/span&gt;
&lt;span&gt;  } &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Done&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Monoid&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;&lt;span&gt; a) &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mappend&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;&lt;span&gt; i1 d1) (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;&lt;span&gt; i2 d2) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;
&lt;span&gt;    &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mappend&lt;/span&gt;&lt;span&gt; i1 i2) (d1 &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;+&lt;/span&gt;&lt;span&gt; d2)&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mappend&lt;/span&gt;&lt;span&gt; e &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Done&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; e&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mappend&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Done&lt;/span&gt;&lt;span&gt; e &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; e&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;mempty&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;&lt;span&gt; [] &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;which itself in the &lt;code style=&#34;white-space: nowrap&#34;&gt;mappend&lt;/code&gt; case uses the &lt;code style=&#34;white-space: nowrap&#34;&gt;Monoid&lt;/code&gt; instance of &lt;code style=&#34;white-space: nowrap&#34;&gt;[]&lt;/code&gt;. I.e. &lt;code&gt;valueToTypes&lt;/code&gt; generates some lists inside &lt;code&gt;Fix TestType&lt;/code&gt; and then you append (and fully force each time!) these lists over and over again just to discard the resulting value via &lt;code&gt;someStuff $ unfix $ ...&lt;/code&gt; later. The now obvious solution is to discard lists immediately while folding:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span&gt;stuff &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; runCConduit &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; sourceTBMChan trees&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;=$=&amp;amp;&lt;/span&gt;&lt;span&gt; foldlC (\x y &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;+&lt;/span&gt;&lt;span&gt; someStuff (unfix y)) &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;0&lt;/span&gt;
&lt;span&gt;Prelude.print stuff&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;which results in a constant-memory profile:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://user-images.githubusercontent.com/10480926/32323747-1ed23a7e-bfda-11e7-8309-1ce5a193d9bf.png&#34; alt&gt;&lt;/p&gt;
&lt;p&gt;By the way, I cannot review your &lt;code style=&#34;white-space: nowrap&#34;&gt;conduit&lt;/code&gt; code as I&amp;#39;m not very familiar with &lt;code style=&#34;white-space: nowrap&#34;&gt;conduit&lt;/code&gt;, but one thing that looks overcomplicated is:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;allInDir ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;MonadResource&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Conduit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FilePath&lt;/span&gt;&lt;span&gt; m (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Fix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;allInDir &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;

&lt;span class=&#34;fu&#34;&gt;readFile&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;MonadResource&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FilePath&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;B.ByteString&lt;/span&gt;
&lt;span class=&#34;fu&#34;&gt;readFile&lt;/span&gt;&lt;span&gt; f &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;  (key, h) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; allocate (openBinaryFile f &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ReadMode&lt;/span&gt;&lt;span&gt;) hClose&lt;/span&gt;
&lt;span&gt;  res &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; liftIO &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; B.hGet h &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;20000000&lt;/span&gt;
&lt;span&gt;  release key&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;pure&lt;/span&gt;&lt;span&gt; res&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What &lt;code style=&#34;white-space: nowrap&#34;&gt;readFile&lt;/code&gt; does is allocates a handle, reads the file and releases the handle. I.e. strictly reads a file. But everything related to &lt;code style=&#34;white-space: nowrap&#34;&gt;ResourceT&lt;/code&gt; it does just inside this single function, so you could as well write:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;fu&#34;&gt;readFile&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FilePath&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;B.ByteString&lt;/span&gt;
&lt;span class=&#34;fu&#34;&gt;readFile&lt;/span&gt;&lt;span&gt; f &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; runResourceT &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;  (key, h) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; allocate (openBinaryFile f &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ReadMode&lt;/span&gt;&lt;span&gt;) hClose&lt;/span&gt;
&lt;span&gt;  res &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; liftIO &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;$&lt;/span&gt;&lt;span&gt; B.hGet h &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;20000000&lt;/span&gt;
&lt;span&gt;  release key&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;pure&lt;/span&gt;&lt;span&gt; res&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But &lt;code&gt;B.ByteString&lt;/code&gt; is already strict, no reason to use
&lt;code style=&#34;white-space: nowrap&#34;&gt;ResourceT&lt;/code&gt; here. Hence the following is sufficient:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;allInDir ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Conduit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FilePath&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Fix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;TestType&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;allInDir &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;...&lt;/span&gt;

&lt;span class=&#34;fu&#34;&gt;readFile&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;FilePath&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;IO&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;B.ByteString&lt;/span&gt;
&lt;span class=&#34;fu&#34;&gt;readFile&lt;/span&gt;&lt;span&gt; f &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;do&lt;/span&gt;
&lt;span&gt;  h &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; openBinaryFile f &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ReadMode&lt;/span&gt;
&lt;span&gt;  res &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; B.hGet h &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;20000000&lt;/span&gt;
&lt;span&gt;  hClose h&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;return&lt;/span&gt;&lt;span&gt; res&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/reactormonk&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/reactormonk.jpeg&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Simon Hafner&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Let me investigate the numbers, so far the write up is top notch. [...] Now I have a rough idea how to look for space leaks. Absolutely worth it.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-10-30-conduit-leak"/></entry><entry><id>2017-10-30-slicing-tensors</id><title type="html">Slicing type-indexed tensors
</title><updated>2017-10-30T00:00:00Z</updated><content type="html">&lt;div id=&#34;2017-10-30-slicing-tensors&#34;&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-highlight&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random6.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;I’d like to write a generalized slicing function, I think it’s doable at the typelevel but I’m not sure how to write out all the constraints.&lt;/p&gt;
&lt;p&gt;The general idea is something like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You have a tensor with shape that’s a type-level list, say, &lt;code style=&#34;white-space: nowrap&#34;&gt;[x,y]&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You have two type level nats, one for the dimension to be sliced and another for the index into that dimension.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The return value should have dimensions that are the same as the tensor, but excluding the selected dimension, so&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code style=&#34;white-space: nowrap&#34;&gt;[x,y]&lt;/code&gt; with dimension &lt;code style=&#34;white-space: nowrap&#34;&gt;0&lt;/code&gt;, index &lt;code style=&#34;white-space: nowrap&#34;&gt;I&lt;/code&gt; ⇒ a tensor of dimension &lt;code style=&#34;white-space: nowrap&#34;&gt;[y]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code style=&#34;white-space: nowrap&#34;&gt;[x,y]&lt;/code&gt; with dimension &lt;code style=&#34;white-space: nowrap&#34;&gt;1&lt;/code&gt;, index &lt;code style=&#34;white-space: nowrap&#34;&gt;I&lt;/code&gt; ⇒ a tensor of dimension &lt;code style=&#34;white-space: nowrap&#34;&gt;[x]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code style=&#34;white-space: nowrap&#34;&gt;[x,y,z]&lt;/code&gt; with dimension &lt;code style=&#34;white-space: nowrap&#34;&gt;1&lt;/code&gt;, index &lt;code style=&#34;white-space: nowrap&#34;&gt;I&lt;/code&gt; ⇒ a tensor of dimension &lt;code style=&#34;white-space: nowrap&#34;&gt;[x,z]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are some constraints, for example &lt;code style=&#34;white-space: nowrap&#34;&gt;I&lt;/code&gt; cannot be less than 0 or bigger than the size in the specified dimension – e.g. for a tensor of &lt;code style=&#34;white-space: nowrap&#34;&gt;[x,y]&lt;/code&gt; you can’t specify dimension &lt;code style=&#34;white-space: nowrap&#34;&gt;0&lt;/code&gt; and index &lt;code style=&#34;white-space: nowrap&#34;&gt;I&lt;/code&gt; if &lt;code style=&#34;white-space: nowrap&#34;&gt;I &amp;gt; x&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are some more complex generalizations on this, for example, ranges of indices, or exclusion of indices, but I want to see if we can come up with a solution for this simple case before moving to harder ones.&lt;/p&gt;
&lt;p&gt;Any thoughts?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/effectfully&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/effectfully.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Roman Kireev&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;Here is a snippet that provides types you want for that exclusion function:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE DataKinds, PolyKinds #-}&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE UndecidableInstances, TypeFamilies #-}&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE AllowAmbiguousTypes, TypeApplications #-}&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;{-# LANGUAGE ScopedTypeVariables, TypeOperators #-}&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;{-# OPTIONS_GHC -Wall #-}&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Main&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;GHC.TypeLits&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;family&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ConsSnd&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;y ::&lt;/span&gt;&lt;span&gt; b) (&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;p ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; (a,[b]))&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; (a,[b]) &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ConsSnd&lt;/span&gt;&lt;span&gt; _  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Nothing&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Nothing&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ConsSnd&lt;/span&gt;&lt;span&gt; y (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Just&lt;/span&gt;&lt;span&gt; (&amp;#39;(,) x ys)) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Just&lt;/span&gt;&lt;span&gt; (&amp;#39;(,) x (y &amp;#39;&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:&lt;/span&gt;&lt;span&gt; ys))&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;family&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExcludeAt&lt;/span&gt;&lt;span&gt; i (&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;xs ::&lt;/span&gt;&lt;span&gt; [a])&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt; ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Maybe&lt;/span&gt;&lt;span&gt; (a,[a]) &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;where&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExcludeAt&lt;/span&gt;&lt;span&gt; _ &amp;#39;[]       &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Nothing&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExcludeAt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;0&lt;/span&gt;&lt;span&gt; (x &amp;#39;&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:&lt;/span&gt;&lt;span&gt; xs) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Just&lt;/span&gt;&lt;span&gt; (&amp;#39;(,) x xs)&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExcludeAt&lt;/span&gt;&lt;span&gt; n (x &amp;#39;&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;:&lt;/span&gt;&lt;span&gt; xs) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ConsSnd&lt;/span&gt;&lt;span&gt; x (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExcludeAt&lt;/span&gt;&lt;span&gt; (n &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;1&lt;/span&gt;&lt;span&gt;) xs)&lt;/span&gt;

&lt;span class=&#34;kw&#34;&gt;data&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;dims ::&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Nat&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;

&lt;span&gt;slice&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;  ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;kw&#34;&gt;forall&lt;/span&gt;&lt;span&gt; dim i n dims dims&amp;#39;&lt;/span&gt;&lt;span class=&#34;op&#34;&gt;.&lt;/span&gt;
&lt;span&gt;     (&lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;ExcludeAt&lt;/span&gt;&lt;span&gt; dim dims &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;~&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;&amp;#39;Just&lt;/span&gt;&lt;span&gt; (&amp;#39;(,) n dims&amp;#39;), &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; i, i &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; n)&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; dims &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; dims&amp;#39;&lt;/span&gt;
&lt;span&gt;slice &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;fu&#34;&gt;undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code style=&#34;white-space: nowrap&#34;&gt;slice&lt;/code&gt; function can be used like this:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;ot&#34;&gt;test1 ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;span&gt;test1 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; slice &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;1&lt;/span&gt;

&lt;span class=&#34;ot&#34;&gt;test2 ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;span&gt;test2 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; slice &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;3&lt;/span&gt;

&lt;span class=&#34;ot&#34;&gt;test3 ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;span&gt;test3 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; slice &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you violate one of the constraints, it fails:&lt;/p&gt;
&lt;div class=&#34;source-code&#34;&gt;&lt;pre&gt;&lt;code class=&#34;language-haskell&#34;&gt;&lt;span class=&#34;co&#34;&gt;-- Couldn&amp;#39;t match &amp;#39;Nothing with &amp;#39;Just&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;fail1 ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;span&gt;fail1 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; slice &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;1&lt;/span&gt;

&lt;span class=&#34;co&#34;&gt;-- Couldn&amp;#39;t match 3 with 2&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;fail2 ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;span&gt;fail2 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; slice &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;

&lt;span class=&#34;co&#34;&gt;-- Couldn&amp;#39;t match &amp;#39;True with &amp;#39;False&lt;/span&gt;
&lt;span class=&#34;ot&#34;&gt;fail3 ::&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;dt&#34;&gt;Tensor&lt;/span&gt;&lt;span&gt; &amp;#39;[&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;span&gt;fail3 &lt;/span&gt;&lt;span class=&#34;ot&#34;&gt;=&lt;/span&gt;&lt;span&gt; slice &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class=&#34;op&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;dv&#34;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-client qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/slack_random6.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Client&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;The type family functions seem so low level, i guess there aren’t many packages for type family functions to plug in for this sort of thing. How does that &lt;code style=&#34;white-space: nowrap&#34;&gt;@Nat&lt;/code&gt; syntax work?&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;qa-message qa-role-consultant qa-msg-casual&#34;&gt;&lt;p class=&#34;qa-author&#34;&gt;&lt;a href=&#34;https://github.com/effectfully&#34;&gt;&lt;img width=&#34;20px&#34; src=&#34;https://monadfix.com/userpics/effectfully.png&#34; class=&#34;qa-userpic&#34;&gt; &lt;strong&gt;&lt;span class=&#34;qa-username&#34;&gt;Roman Kireev&lt;/span&gt;:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;qa-content&#34;&gt;&lt;p&gt;There is the &lt;a href=&#34;https://hackage.haskell.org/package/singletons&#34;&gt;&lt;code style=&#34;white-space: nowrap&#34;&gt;singletons&lt;/code&gt;&lt;/a&gt; package which provides &lt;a href=&#34;https://typesandkinds.wordpress.com/2013/04/01/defunctionalization-for-the-win/&#34;&gt;the defunctionalization gadget&lt;/a&gt; which can be used in order to implement higher-order functions at the type level. It also contains a lot of functions promoted to type families.&lt;/p&gt;
&lt;p&gt;That &lt;code style=&#34;white-space: nowrap&#34;&gt;@&lt;/code&gt; syntax is enabled by &lt;code style=&#34;white-space: nowrap&#34;&gt;-XTypeApplications&lt;/code&gt;. Basically, instead of passing &lt;code style=&#34;white-space: nowrap&#34;&gt;Proxy&lt;/code&gt;s around you explicitly specify type parameters via type applications. In &lt;code&gt;slice @0 @1&lt;/code&gt;, the &lt;code style=&#34;white-space: nowrap&#34;&gt;0&lt;/code&gt; argument is for &lt;code style=&#34;white-space: nowrap&#34;&gt;dim&lt;/code&gt; and the &lt;code style=&#34;white-space: nowrap&#34;&gt;1&lt;/code&gt; is for &lt;code style=&#34;white-space: nowrap&#34;&gt;i&lt;/code&gt;. This is nicer than &lt;code&gt;proxySlice (Proxy :: Proxy 0) (Proxy :: Proxy 1)&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link href="https://monadfix.com#2017-10-30-slicing-tensors"/></entry></feed>