fixing a bunch of broken stuff I think
This commit is contained in:
parent
0dbc3ead0e
commit
8bace887a2
1551 changed files with 299 additions and 57481 deletions
|
@ -1 +0,0 @@
|
|||
<table> <tr><td> <a href="https://www.reddit.com/r/unixporn/comments/rrdfse/bspwm_neovim/"> <img src="https://preview.redd.it/313fkhmlni881.jpg?width=640&crop=smart&auto=webp&s=7a48df4e4b93e3543cfdb48bbe3e9351c8bff6f7" alt="[bspwm] Neovim" title="[bspwm] Neovim" /> </a> </td><td>   submitted by   <a href="https://www.reddit.com/user/Asta101Clover"> /u/Asta101Clover </a> <br/> <span><a href="https://i.redd.it/313fkhmlni881.jpg">[link]</a></span>   <span><a href="https://www.reddit.com/r/unixporn/comments/rrdfse/bspwm_neovim/">[comments]</a></span> </td></tr></table>
|
|
@ -1,378 +0,0 @@
|
|||
<p>
|
||||
In a tool I'm writing I want to load a file that may reside on the local disk,
|
||||
but if it isn't there I want to fetch it from the web. Basically it's very
|
||||
similar to having a cache and dealing with a miss, except in my case I don't
|
||||
populate the cache.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let me first define the functions to play with
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-haskell"><span class="org-haskell-definition">loadFromDisk</span> <span class="org-haskell-operator">::</span> <span class="org-haskell-type">String</span> <span class="org-haskell-operator">-></span> <span class="org-haskell-type">IO</span> <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> <span class="org-haskell-type">String</span> <span class="org-haskell-type">Int</span><span class="org-rainbow-delimiters-depth-1">)</span>
|
||||
<span class="org-haskell-definition">loadFromDisk</span> k<span class="org-haskell-operator">@</span><span class="org-string">"bad key"</span> <span class="org-haskell-operator">=</span> <span class="org-haskell-keyword">do</span>
|
||||
putStrLn <span class="org-haskell-operator">$</span> <span class="org-string">"local: "</span> <span class="org-haskell-operator"><></span> k
|
||||
pure <span class="org-haskell-operator">$</span> <span class="org-haskell-constructor">Left</span> <span class="org-haskell-operator">$</span> <span class="org-string">"no such local key: "</span> <span class="org-haskell-operator"><></span> k
|
||||
<span class="org-haskell-definition">loadFromDisk</span> k <span class="org-haskell-operator">=</span> <span class="org-haskell-keyword">do</span>
|
||||
putStrLn <span class="org-haskell-operator">$</span> <span class="org-string">"local: "</span> <span class="org-haskell-operator"><></span> k
|
||||
pure <span class="org-haskell-operator">$</span> <span class="org-haskell-constructor">Right</span> <span class="org-haskell-operator">$</span> length k
|
||||
|
||||
<span class="org-haskell-definition">loadFromWeb</span> <span class="org-haskell-operator">::</span> <span class="org-haskell-type">String</span> <span class="org-haskell-operator">-></span> <span class="org-haskell-type">IO</span> <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> <span class="org-haskell-type">String</span> <span class="org-haskell-type">Int</span><span class="org-rainbow-delimiters-depth-1">)</span>
|
||||
<span class="org-haskell-definition">loadFromWeb</span> k<span class="org-haskell-operator">@</span><span class="org-string">"bad key"</span> <span class="org-haskell-operator">=</span> <span class="org-haskell-keyword">do</span>
|
||||
putStrLn <span class="org-haskell-operator">$</span> <span class="org-string">"web: "</span> <span class="org-haskell-operator"><></span> k
|
||||
pure <span class="org-haskell-operator">$</span> <span class="org-haskell-constructor">Left</span> <span class="org-haskell-operator">$</span> <span class="org-string">"no such remote key: "</span> <span class="org-haskell-operator"><></span> k
|
||||
<span class="org-haskell-definition">loadFromWeb</span> k <span class="org-haskell-operator">=</span> <span class="org-haskell-keyword">do</span>
|
||||
putStrLn <span class="org-haskell-operator">$</span> <span class="org-string">"web: "</span> <span class="org-haskell-operator"><></span> k
|
||||
pure <span class="org-haskell-operator">$</span> <span class="org-haskell-constructor">Right</span> <span class="org-haskell-operator">$</span> length k
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="outline-2" id="outline-container-org79c5c1e">
|
||||
<h2 id="org79c5c1e">Discarded solution: using the <code>Alternative</code> of <code>IO</code> directly</h2>
|
||||
<div class="outline-text-2" id="text-org79c5c1e">
|
||||
<p>
|
||||
It's fairly easy to get the desired behaviour but <code>Alternative</code> of <code>IO</code> is based
|
||||
on exceptions which doesn't strike me as a good idea unless one is using <code>IO</code>
|
||||
directly. That is fine in a smallish application, but in my case it makes sense
|
||||
to use tagless style (or <code>ReaderT</code> pattern) so I'll skip exploring this option
|
||||
completely.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="outline-2" id="outline-container-org74c8945">
|
||||
<h2 id="org74c8945">First attempt: lifting into the <code>Alternative</code> of <code>Either e</code></h2>
|
||||
<div class="outline-text-2" id="text-org74c8945">
|
||||
<p>
|
||||
There's an instance of <code>Alternative</code> for <code>Either e</code> in version 0.5 of
|
||||
<a href="https://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-Monad-Trans-Error.html#section.orphans">transformers</a>. It's deprecated and it's gone in newer versions of the library as
|
||||
one really should use <code>Except</code> or <code>ExceptT</code> instead. Even if I don't think it's
|
||||
where I want to end up, it's not an altogether bad place to start.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Now let's define a function using <code>liftA2 (<|>)</code> to make it easy to see what the
|
||||
behaviour is
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-haskell"><span class="org-haskell-definition">fallBack</span> <span class="org-haskell-operator">::</span>
|
||||
<span class="org-haskell-type">Applicative</span> m <span class="org-haskell-operator">=></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> <span class="org-haskell-type">String</span> res<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> <span class="org-haskell-type">String</span> res<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> <span class="org-haskell-type">String</span> res<span class="org-rainbow-delimiters-depth-1">)</span>
|
||||
<span class="org-haskell-definition">fallBack</span> <span class="org-haskell-operator">=</span> liftA2 <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-operator"><|></span><span class="org-rainbow-delimiters-depth-1">)</span>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<pre class="example" id="org1f6b3a0">λ> loadFromDisk "bad key" `fallBack` loadFromWeb "good key"
|
||||
local: bad key
|
||||
web: good key
|
||||
Right 8
|
||||
|
||||
λ> loadFromDisk "bad key" `fallBack` loadFromWeb "bad key"
|
||||
local: bad key
|
||||
web: bad key
|
||||
Left "no such remote key: bad key"
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The first example shows that it falls back to loading form the web, and the
|
||||
second one shows that it's only the last failure that survives. The latter part,
|
||||
that only the last failure survives, isn't ideal but I think I can live with
|
||||
that. If I were interested in collecting all failures I would reach for
|
||||
<code>Validation</code> from <a href="https://hackage.haskell.org/package/validation-selective"><code>validation-selective</code></a> (there's one in <a href="https://hackage.haskell.org/package/validation-selective"><code>validation</code></a> that
|
||||
should work too).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
So far so good, but the next example shows a behaviour I don't want
|
||||
</p>
|
||||
|
||||
<pre class="example" id="org005ead3">λ> loadFromDisk "good key" `fallBack` loadFromWeb "good key"
|
||||
local: good key
|
||||
web: good key
|
||||
Right 8
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
or to make it even more explicit
|
||||
</p>
|
||||
|
||||
<pre class="example" id="orgf34f455">λ> loadFromDisk "good key" `fallBack` undefined
|
||||
local: good key
|
||||
*** Exception: Prelude.undefined
|
||||
CallStack (from HasCallStack):
|
||||
error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err
|
||||
undefined, called at <interactive>:451:36 in interactive:Ghci4
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
There's no short-circuiting!<sup><a class="footref" href="https://magnus.therning.org/feed.xml#fn.1" id="fnr.1">1</a></sup>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The behaviour I want is of course that if the first action is successful, then
|
||||
the second action shouldn't take place at all.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It looks like either <code><|></code> is strict in its second argument, or maybe it's
|
||||
<code>liftA2</code> that forces it. I've not bothered digging into the details, it's enough
|
||||
to observe it to realise that this approach isn't good enough.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="outline-2" id="outline-container-second-attempt">
|
||||
<h2 id="second-attempt">Second attempt: cutting it short, manually</h2>
|
||||
<div class="outline-text-2" id="text-second-attempt">
|
||||
<p>
|
||||
Fixing the lack of short-circuiting the evaluation after the first success isn't
|
||||
too difficult to do manually. Something like this does it
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-haskell"><span class="org-haskell-definition">fallBack</span> <span class="org-haskell-operator">::</span>
|
||||
<span class="org-haskell-type">Monad</span> m <span class="org-haskell-operator">=></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> <span class="org-haskell-type">String</span> a<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> <span class="org-haskell-type">String</span> a<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> <span class="org-haskell-type">String</span> a<span class="org-rainbow-delimiters-depth-1">)</span>
|
||||
<span class="org-haskell-definition">fallBack</span> first other <span class="org-haskell-operator">=</span> <span class="org-haskell-keyword">do</span>
|
||||
first <span class="org-haskell-operator">>>=</span> <span class="org-haskell-operator">\</span><span class="org-haskell-keyword">case</span>
|
||||
r<span class="org-haskell-operator">@</span><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-constructor">Right</span> <span class="org-haskell-keyword">_</span><span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span> pure r
|
||||
r<span class="org-haskell-operator">@</span><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-constructor">Left</span> <span class="org-haskell-keyword">_</span><span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span> <span class="org-rainbow-delimiters-depth-1">(</span>r <span class="org-haskell-operator"><|></span><span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator"><$></span> other
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
It does indeed show the behaviour I want
|
||||
</p>
|
||||
|
||||
<pre class="example" id="org0bc7069">λ> loadFromDisk "bad key" `fallBack` loadFromWeb "good key"
|
||||
local: bad key
|
||||
web: good key
|
||||
Right 8
|
||||
|
||||
λ> loadFromDisk "bad key" `fallBack` loadFromWeb "bad key"
|
||||
local: bad key
|
||||
web: bad key
|
||||
Left "no such remote key: bad key"
|
||||
|
||||
λ> loadFromDisk "good key" `fallBack` undefined
|
||||
local: good key
|
||||
Right 8
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Excellent! And to switch over to use <code>Validation</code> one just have to switch
|
||||
constructors, <code>Right</code> becomes <code>Success</code> and <code>Left</code> becomes <code>Failure</code>. Though
|
||||
collecting the failures by concatenating strings isn't the best idea of course.
|
||||
Switching to some other <code>Monoid</code> (that's the constraint on the failure type)
|
||||
isn't too difficult.
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-haskell"><span class="org-haskell-definition">fallBack</span> <span class="org-haskell-operator">::</span>
|
||||
<span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Monad</span> m, <span class="org-haskell-type">Monoid</span> e<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">=></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Validation</span> e a<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Validation</span> e a<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Validation</span> e a<span class="org-rainbow-delimiters-depth-1">)</span>
|
||||
<span class="org-haskell-definition">fallBack</span> first other <span class="org-haskell-operator">=</span> <span class="org-haskell-keyword">do</span>
|
||||
first <span class="org-haskell-operator">>>=</span> <span class="org-haskell-operator">\</span><span class="org-haskell-keyword">case</span>
|
||||
r<span class="org-haskell-operator">@</span><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-constructor">Success</span> <span class="org-haskell-keyword">_</span><span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span> pure r
|
||||
r<span class="org-haskell-operator">@</span><span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-constructor">Failure</span> <span class="org-haskell-keyword">_</span><span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span> <span class="org-rainbow-delimiters-depth-1">(</span>r <span class="org-haskell-operator"><|></span><span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator"><$></span> other
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="outline-2" id="outline-container-orgbc3f08f">
|
||||
<h2 id="orgbc3f08f">Third attempt: pulling failures out to <code>MonadPlus</code></h2>
|
||||
<div class="outline-text-2" id="text-orgbc3f08f">
|
||||
<p>
|
||||
After writing the <code>fallBack</code> function I still wanted to explore other solutions.
|
||||
There's almost always something more out there in the Haskell eco system, right?
|
||||
So I asked in the <i>#haskell-beginners</i> channel on the Functional Programming
|
||||
Slack. The way I asked the question resulted in answers that iterates over a
|
||||
list of actions and cutting at the first success.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The first suggestion had me a little confused at first, but once I re-organised
|
||||
the helper function a little it made more sense to me.
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-haskell"><span class="org-haskell-definition">mFromRight</span> <span class="org-haskell-operator">::</span> <span class="org-haskell-type">MonadPlus</span> m <span class="org-haskell-operator">=></span> m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> err res<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span> m res
|
||||
<span class="org-haskell-definition">mFromRight</span> <span class="org-haskell-operator">=</span> <span class="org-rainbow-delimiters-depth-1">(</span>either <span class="org-rainbow-delimiters-depth-2">(</span>const mzero<span class="org-rainbow-delimiters-depth-2">)</span> return <span class="org-haskell-operator">=<<</span><span class="org-rainbow-delimiters-depth-1">)</span>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
To use it put the actions in a list, map the helper above, and finally run
|
||||
<code>asum</code> on it all<sup><a class="footref" href="https://magnus.therning.org/feed.xml#fn.2" id="fnr.2">2</a></sup>. I think it makes it a little clearer what happens if
|
||||
it's rewritten like this.
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-haskell"><span class="org-haskell-definition">firstRightM</span> <span class="org-haskell-operator">::</span> <span class="org-haskell-type">MonadPlus</span> m <span class="org-haskell-operator">=></span> <span class="org-rainbow-delimiters-depth-1">[</span>m <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-haskell-type">Either</span> err res<span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">]</span> <span class="org-haskell-operator">-></span> m res
|
||||
<span class="org-haskell-definition">firstRightM</span> <span class="org-haskell-operator">=</span> asum <span class="org-haskell-operator">.</span> fmap go
|
||||
<span class="org-haskell-keyword">where</span>
|
||||
go m <span class="org-haskell-operator">=</span> m <span class="org-haskell-operator">>>=</span> either <span class="org-rainbow-delimiters-depth-1">(</span>const mzero<span class="org-rainbow-delimiters-depth-1">)</span> return
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<pre class="example" id="org46be250">λ> firstRightM [loadFromDisk "bad key", loadFromWeb "good key"]
|
||||
local: bad key
|
||||
web: good key
|
||||
8
|
||||
|
||||
λ> firstRightM [loadFromDisk "good key", undefined]
|
||||
local: good key
|
||||
8
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
So far so good, but I left out the case where both fail, because that's sort of
|
||||
the fly in the ointment here
|
||||
</p>
|
||||
|
||||
<pre class="example" id="orgdda08c7">λ> firstRightM [loadFromDisk "bad key", loadFromWeb "bad key"]
|
||||
local: bad key
|
||||
web: bad key
|
||||
*** Exception: user error (mzero)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
It's not nice to be back to deal with exceptions, but it's possible to recover,
|
||||
e.g. by appending <code><|> pure 0</code>.
|
||||
</p>
|
||||
|
||||
<pre class="example" id="org3555519">λ> firstRightM [loadFromDisk "bad key", loadFromWeb "bad key"] <|> pure 0
|
||||
local: bad key
|
||||
web: bad key
|
||||
0
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
However that removes the ability to deal with the situation where all actions
|
||||
fail. Not nice! Add to that the difficulty of coming up with a <i>good</i>
|
||||
<code>MonadPlus</code> instance for an application monad; one basically have to resort to
|
||||
the same thing as for <code>IO</code>, i.e. to throw an exception. Also not nice!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="outline-2" id="outline-container-fourth-attempt">
|
||||
<h2 id="fourth-attempt">Fourth attempt: wrapping in <code>ExceptT</code> to get its <code>Alternative</code> behaviour</h2>
|
||||
<div class="outline-text-2" id="text-fourth-attempt">
|
||||
<p>
|
||||
This was another suggestion from the Slack channel, and it is the one I like the
|
||||
most. Again it was suggested as a way to stop at the first successful action in
|
||||
a list of actions.
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-haskell"><span class="org-haskell-definition">firstRightM</span> <span class="org-haskell-operator">::</span>
|
||||
<span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Foldable</span> t, <span class="org-haskell-type">Functor</span> t, <span class="org-haskell-type">Monad</span> m, <span class="org-haskell-type">Monoid</span> err<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">=></span>
|
||||
t <span class="org-rainbow-delimiters-depth-1">(</span>m <span class="org-rainbow-delimiters-depth-2">(</span><span class="org-haskell-type">Either</span> err res<span class="org-rainbow-delimiters-depth-2">)</span><span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> err res<span class="org-rainbow-delimiters-depth-1">)</span>
|
||||
<span class="org-haskell-definition">firstRightM</span> <span class="org-haskell-operator">=</span> runExceptT <span class="org-haskell-operator">.</span> asum <span class="org-haskell-operator">.</span> fmap <span class="org-haskell-constructor">ExceptT</span>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Which can be used similarly to the previous one. It's also easy to write a
|
||||
variant of <code>fallBack</code> for it.
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-haskell"><span class="org-haskell-definition">fallBack</span> <span class="org-haskell-operator">::</span>
|
||||
<span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Monad</span> m, <span class="org-haskell-type">Monoid</span> err<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">=></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> err res<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> err res<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span>
|
||||
m <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Either</span> err res<span class="org-rainbow-delimiters-depth-1">)</span>
|
||||
<span class="org-haskell-definition">fallBack</span> first other <span class="org-haskell-operator">=</span> runExceptT <span class="org-haskell-operator">$</span> <span class="org-haskell-constructor">ExceptT</span> first <span class="org-haskell-operator"><|></span> <span class="org-haskell-constructor">ExceptT</span> other
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<pre class="example" id="org2366803">λ> loadFromDisk "bad key" `fallBack` loadFromWeb "good key"
|
||||
local: bad key
|
||||
web: good key
|
||||
Right 8
|
||||
|
||||
λ> loadFromDisk "good key" `fallBack` undefined
|
||||
local: good key
|
||||
Right 8
|
||||
|
||||
λ> loadFromDisk "bad key" `fallBack` loadFromWeb "bad key"
|
||||
local: bad key
|
||||
web: bad key
|
||||
Left "no such local key: bad keyno such remote key: bad key"
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Yay! This solution has the short-circuiting behaviour I want, as well as
|
||||
collecting all errors on failure.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="outline-2" id="outline-container-orgc7c8216">
|
||||
<h2 id="orgc7c8216">Conclusion</h2>
|
||||
<div class="outline-text-2" id="text-orgc7c8216">
|
||||
<p>
|
||||
I'm still a little disappointed that <code>liftA2 (<|>)</code> isn't short-circuiting as I
|
||||
still think it's the easiest of the approaches. However, it's a problem that one
|
||||
has to rely on a deprecated instance of <code>Alternative</code> for <code>Either String</code>,
|
||||
but switching to use <code>Validation</code> would be only a minor change.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Manually writing the <code>fallBack</code> function, as I did in the <a href="https://magnus.therning.org/feed.xml#second-attempt">second attempt</a>,
|
||||
results in very explicit code which is nice as it often reduces the cognitive
|
||||
load for the reader. It's a contender, but using the deprecated <code>Alternative</code>
|
||||
instance is problematic and introducing <code>Validition</code>, an arguably not very
|
||||
common type, takes away a little of the appeal.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the end I prefer the <a href="https://magnus.therning.org/feed.xml#fourth-attempt">fourth attempt</a>. It behaves exactly like I want and even
|
||||
though <code>ExpectT</code> lives in <i>transformers</i> I feel that it (I pull it in via <i>mtl</i>)
|
||||
is in such wide use that most Haskell programmers will be familiar with it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One final thing to add is that the <a href="https://hackage.haskell.org/package/validation-selective-0.1.0.1/docs/Validation.html">documentation of <code>Validation</code></a> is an excellent
|
||||
inspiration when it comes to the behaviour of its instances. I wish that the
|
||||
documentation of other packages, in particular commonly used ones like <i>base</i>,
|
||||
<i>transformers</i>, and <i>mtl</i>, would be more like it.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footnotes">
|
||||
<h2 class="footnotes">Footnotes: </h2>
|
||||
<div id="text-footnotes">
|
||||
|
||||
<div class="footdef"><sup><a class="footnum" href="https://magnus.therning.org/feed.xml#fnr.1" id="fn.1">1</a></sup> <div class="footpara"><p class="footpara">
|
||||
I'm not sure if it's a good term to use in this case as <a href="https://en.wikipedia.org/wiki/Short-circuit_evaluation">Wikipedia</a> says
|
||||
it's for Boolean operators. I hope it's not too far a stretch to use it in this
|
||||
context too.
|
||||
</p></div></div>
|
||||
|
||||
<div class="footdef"><sup><a class="footnum" href="https://magnus.therning.org/feed.xml#fnr.2" id="fn.2">2</a></sup> <div class="footpara"><p class="footpara">
|
||||
In the version of <i>base</i> I'm using there is no <code>asum</code>, so I simply copied
|
||||
the implementation from a later version:
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-haskell"><span class="org-haskell-definition">asum</span> <span class="org-haskell-operator">::</span> <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-type">Foldable</span> t, <span class="org-haskell-type">Alternative</span> f<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">=></span> t <span class="org-rainbow-delimiters-depth-1">(</span>f a<span class="org-rainbow-delimiters-depth-1">)</span> <span class="org-haskell-operator">-></span> f a
|
||||
<span class="org-haskell-definition">asum</span> <span class="org-haskell-operator">=</span> foldr <span class="org-rainbow-delimiters-depth-1">(</span><span class="org-haskell-operator"><|></span><span class="org-rainbow-delimiters-depth-1">)</span> empty
|
||||
</pre>
|
||||
</div></div></div>
|
||||
|
||||
|
||||
</div>
|
||||
</div><div class="taglist"><a href="https://magnus.therning.org/tags.html">Tags</a>: <a href="https://magnus.therning.org/tag-alternative_typeclass.html">alternative_typeclass</a> <a href="https://magnus.therning.org/tag-caching.html">caching</a> <a href="https://magnus.therning.org/tag-fallback.html">fallback</a> <a href="https://magnus.therning.org/tag-haskell.html">haskell</a> </div>
|
|
@ -1 +0,0 @@
|
|||
<!-- SC_OFF --><div class="md"><p>I'm doing this year's <a href="https://adventofcode.com/">Advent of Code</a> in Emacs Lisp. Is anyone else trying it this year?</p> <p>I'd love some feedback on my solutions!</p> <p><strong>Day 1</strong></p> <pre><code>(defun read-lines (filePath) "Return a list of lines of a file at filePath." (with-temp-buffer (insert-file-contents filePath) (split-string (buffer-string) "\n" t))) (setq measurements (mapcar #'string-to-number (read-lines "day-1-input.txt"))) (defun count-increases (func) (let ((iter-list measurements) (num-increases 0)) (while iter-list (if (< (pop iter-list) (or (funcall func iter-list) 0)) (cl-incf num-increases))) num-increases)) ;; Part 1 (count-increases #'car) ;; Part 2 (count-increases #'caddr) </code></pre> </div><!-- SC_ON -->   submitted by   <a href="https://www.reddit.com/user/-cvdub-"> /u/-cvdub- </a> <br/> <span><a href="https://www.reddit.com/r/emacs/comments/r7kk9n/advent_of_code_in_elisp_spoilers/">[link]</a></span>   <span><a href="https://www.reddit.com/r/emacs/comments/r7kk9n/advent_of_code_in_elisp_spoilers/">[comments]</a></span>
|
|
@ -1,4 +0,0 @@
|
|||
<p><a href="https://www.lfg.co/page/1563/" rel="bookmark" title="1563"><img width="210" height="300" src="https://www.lfg.co/wp-content/uploads/2021/12/lfg5619-1559-dec06-21-210x300.jpg" class="attachment-medium size-medium wp-post-image" alt="" srcset="https://www.lfg.co/wp-content/uploads/2021/12/lfg5619-1559-dec06-21-210x300.jpg 210w, https://www.lfg.co/wp-content/uploads/2021/12/lfg5619-1559-dec06-21-105x150.jpg 105w, https://www.lfg.co/wp-content/uploads/2021/12/lfg5619-1559-dec06-21.jpg 700w" sizes="(max-width: 210px) 100vw, 210px" /></a></p>
|
||||
<p>The post <a rel="nofollow" href="https://www.lfg.co/page/1563/">1563</a> appeared first on <a rel="nofollow" href="https://www.lfg.co">Looking For Group</a>.</p><div class="feedflare">
|
||||
<a href="http://feeds.feedburner.com/~ff/LookingForGroup?a=9L9lyWWRnmQ:01T4kMDj7eI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/LookingForGroup?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LookingForGroup?a=9L9lyWWRnmQ:01T4kMDj7eI:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/LookingForGroup?i=9L9lyWWRnmQ:01T4kMDj7eI:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/LookingForGroup?a=9L9lyWWRnmQ:01T4kMDj7eI:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/LookingForGroup?d=7Q72WNTAKBA" border="0"></img></a>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
<!-- SC_OFF --><div class="md"><p>Github (and gitlab) is completely blocked by company. I am using Doom-emacs at the moment. Not sure there's any possible way to use Emacs without github access?</p> <p>(possible to mirror some github repos onto local git server).</p> </div><!-- SC_ON -->   submitted by   <a href="https://www.reddit.com/user/enzechi"> /u/enzechi </a> <br/> <span><a href="https://www.reddit.com/r/emacs/comments/r7k4wr/how_to_use_emacs_without_github_access/">[link]</a></span>   <span><a href="https://www.reddit.com/r/emacs/comments/r7k4wr/how_to_use_emacs_without_github_access/">[comments]</a></span>
|
File diff suppressed because it is too large
Load diff
|
@ -1 +0,0 @@
|
|||
<!-- SC_OFF --><div class="md"><p>hi everybody,</p> <p>i use auctex to edit latex (in Linux, mostly).</p> <p>As I move around the document in latex, I would like the pdf view (either inside emacs or ouside, I could adapt to either one) to jump to the page that corresponds to the area in the latex document I am editing. Is this possible?</p> <p>I know it is possible to do it the other way around (click on the pdf, jump to the corresponding latex).</p> <p>thank you in advance for any hints/information.</p> </div><!-- SC_ON -->   submitted by   <a href="https://www.reddit.com/user/dm_g"> /u/dm_g </a> <br/> <span><a href="https://www.reddit.com/r/emacs/comments/r55ho4/auctex_and_automatic_display_of_page/">[link]</a></span>   <span><a href="https://www.reddit.com/r/emacs/comments/r55ho4/auctex_and_automatic_display_of_page/">[comments]</a></span>
|
|
@ -1 +0,0 @@
|
|||
<!-- SC_OFF --><div class="md"><p>When we are in the middle of a line, <code>open-line</code> splits current line at the cursor while saving the cursor's position, but the opened line below isn't indented.</p> <p>Is there a version which can indent the line below? </p> <p>"RET C-p C-e" seems a bit verbose.</p> <p>I can write a simple command line <code>(save-excursion (newline-and-indent))</code> but I'd love to know if there are any existing ones.</p> <p>Edit: use case (assume that the cursor is at "|"):</p> <pre><code> <html-tag|></html-tag> <!-- What C-o does --> <html-tag| ></html-tag> <!-- What M-j does --> <html-tag |></html-tag> <!-- What I need --> <html-tag| <!-- we write the attributes here --> ></html-tag> <!-- This is great, too! --> <html-tag | ></html-tag> </code></pre> <p>Edit: explained the use case more thoroughly.</p> </div><!-- SC_ON -->   submitted by   <a href="https://www.reddit.com/user/takutekato"> /u/takutekato </a> <br/> <span><a href="https://www.reddit.com/r/emacs/comments/rcfggm/is_there_an_indented_version_of_openline/">[link]</a></span>   <span><a href="https://www.reddit.com/r/emacs/comments/rcfggm/is_there_an_indented_version_of_openline/">[comments]</a></span>
|
Loading…
Add table
Add a link
Reference in a new issue