<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: mrkeen</title><link>https://news.ycombinator.com/user?id=mrkeen</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Thu, 16 Apr 2026 13:40:14 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=mrkeen" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by mrkeen in "Stop Using Ollama"]]></title><description><![CDATA[
<p>I've now given ramalama a look:<p>--<p><pre><code>  % ramalama run qwen3.5   
   > hi

  Server or container exited. Shutting down client.
</code></pre>
--<p><pre><code>  % ramalama run gemma4:e2b
   > hello

  Server or container exited. Shutting down client.
</code></pre>
--</p>
]]></description><pubDate>Thu, 16 Apr 2026 08:14:05 +0000</pubDate><link>https://news.ycombinator.com/item?id=47790142</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47790142</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47790142</guid></item><item><title><![CDATA[New comment by mrkeen in "The local LLM ecosystem doesn’t need Ollama"]]></title><description><![CDATA[
<p>> Red Hat’s ramalama is worth a look too, a container-native model runner that explicitly credits its upstream dependencies front and center. Exactly what Ollama should have done from the start.<p><pre><code>  % ramalama run qwen3.5-9b
  Error: Manifest for qwen3.5-9b:latest was not found in the Ollama registry</code></pre></p>
]]></description><pubDate>Thu, 16 Apr 2026 08:05:10 +0000</pubDate><link>https://news.ycombinator.com/item?id=47790084</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47790084</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47790084</guid></item><item><title><![CDATA[New comment by mrkeen in "Want to write a compiler? Just read these two papers (2008)"]]></title><description><![CDATA[
<p>I'll push back and say that the lexer/parser split is well worth it.<p>And the best thing about the parser combinator approach is that each is just a kind of parser, something like<p><pre><code>  type Lexer = ParsecT e ByteString m [Token]

  type Parser = ParsecT e [Token] Expr
</code></pre>
All the usual helper functions like <i>many</i> or <i>sepBy</i> work equally well in the lexing and parsing phases.<p>It really beats getting to the parentheses-interacting-with-ordering-of-division-operations stage and still having to think "have I already trimmed off the whitespace here or not?"</p>
]]></description><pubDate>Wed, 15 Apr 2026 11:50:23 +0000</pubDate><link>https://news.ycombinator.com/item?id=47777811</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47777811</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47777811</guid></item><item><title><![CDATA[New comment by mrkeen in "GPT-5.4 Pro solves Erdős Problem #1196"]]></title><description><![CDATA[
<p>What's the conflict?</p>
]]></description><pubDate>Wed, 15 Apr 2026 06:39:56 +0000</pubDate><link>https://news.ycombinator.com/item?id=47775498</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47775498</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47775498</guid></item><item><title><![CDATA[New comment by mrkeen in "Understanding Clojure's Persistent Vectors, pt. 1 (2013)"]]></title><description><![CDATA[
<p>Because standard libraries in mainstream languages are name-squatting on 'immutable' pretty hard.<p>You wanted 2+1 to yield 3, but instead you get a runtime exception telling you that 2 can't be changed.</p>
]]></description><pubDate>Wed, 15 Apr 2026 06:29:29 +0000</pubDate><link>https://news.ycombinator.com/item?id=47775425</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47775425</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47775425</guid></item><item><title><![CDATA[New comment by mrkeen in "Surelock: Deadlock-Free Mutexes for Rust"]]></title><description><![CDATA[
<p>> unbounded TM is likely a fool’s errand<p>It's the whole language, not just the TM code.  Other languages have no way of <i>opting out</i> of the TM code, whereas Haskell does.</p>
]]></description><pubDate>Sun, 12 Apr 2026 06:15:03 +0000</pubDate><link>https://news.ycombinator.com/item?id=47736640</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47736640</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47736640</guid></item><item><title><![CDATA[New comment by mrkeen in "My university uses prompt injection to catch cheaters"]]></title><description><![CDATA[
<p>Which is it?<p>By withholding calculators, did your teachers prove you understood the fundamentals?  Or did they actively hamper your ability to compete mathematically?</p>
]]></description><pubDate>Mon, 06 Apr 2026 20:29:51 +0000</pubDate><link>https://news.ycombinator.com/item?id=47666603</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47666603</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47666603</guid></item><item><title><![CDATA[New comment by mrkeen in "Category Theory Illustrated – Types"]]></title><description><![CDATA[
<p>Oof.  If sets and types aren't the same, then sets and barbers are <i>definitely</i> not the same!</p>
]]></description><pubDate>Fri, 03 Apr 2026 22:17:59 +0000</pubDate><link>https://news.ycombinator.com/item?id=47633064</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47633064</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47633064</guid></item><item><title><![CDATA[New comment by mrkeen in "Category Theory Illustrated – Types"]]></title><description><![CDATA[
<p>TFA is right.  Parent comment is not really rebutting in any meaningful way.  Your rebuttal makes less sense.<p>>> "a term can have only one <i>type</i>... Due to this law, <i>types</i> cannot contain themselves"<p>> types are not sets and sets are not types therefore it makes no sense to link these two statements/judgements in the way you are linking them</p>
]]></description><pubDate>Fri, 03 Apr 2026 21:59:59 +0000</pubDate><link>https://news.ycombinator.com/item?id=47632889</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47632889</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47632889</guid></item><item><title><![CDATA[New comment by mrkeen in "Category Theory Illustrated – Types"]]></title><description><![CDATA[
<p>The system works according to its defined rules.<p>In one system, a set can contain itself, in another system it can't.<p>So it doesn't really make sense to ask 'can it?'<p>If you allow sets to contain themselves, you also have to talk about sets which do not contain themselves, which yields Russell's paradox.<p>If you disallow sets (or types) from containing themselves then you can't construct Russell's paradox, which is why it follows.</p>
]]></description><pubDate>Fri, 03 Apr 2026 21:50:58 +0000</pubDate><link>https://news.ycombinator.com/item?id=47632798</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47632798</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47632798</guid></item><item><title><![CDATA[New comment by mrkeen in "LinkedIn is searching your browser extensions"]]></title><description><![CDATA[
<p>Yep, LinkedIn is cancer.<p>2020 - LinkedIn Sued For Spying on Clipboard Data After iOS 14 Exposes Its App:<p><a href="https://wccftech.com/linkedin-sued-for-spying-on-clipboard-data-after-ios-14-exposes-its-app/" rel="nofollow">https://wccftech.com/linkedin-sued-for-spying-on-clipboard-d...</a><p>2013 - LinkedIn MITM attacks your iPhone to read your mail:<p><a href="https://www.troyhunt.com/disassembling-privacy-implications-of/" rel="nofollow">https://www.troyhunt.com/disassembling-privacy-implications-...</a><p>2012/2016 - Data breach of 164.6 million accounts:<p><a href="https://haveibeenpwned.com/breach/LinkedIn" rel="nofollow">https://haveibeenpwned.com/breach/LinkedIn</a><p>According to haveibeenpwned.com, my email & password were leaked in both the 'May 2012' and 'April 2021' LinkedIn incidents.</p>
]]></description><pubDate>Thu, 02 Apr 2026 17:49:16 +0000</pubDate><link>https://news.ycombinator.com/item?id=47617742</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47617742</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47617742</guid></item><item><title><![CDATA[New comment by mrkeen in "LinkedIn is searching your browser extensions"]]></title><description><![CDATA[
<p>No company would treat it as either-or.<p>If websites could charge 5.99/month, they would.<p>If a website was charging 5.99/month, they would not stop spying on you.</p>
]]></description><pubDate>Thu, 02 Apr 2026 15:25:33 +0000</pubDate><link>https://news.ycombinator.com/item?id=47615744</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47615744</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47615744</guid></item><item><title><![CDATA[New comment by mrkeen in "The "Vibe Coding" Wall of Shame"]]></title><description><![CDATA[
<p>> Why is the LiteLLM incident on there? The linked article for that one is a 404.<p>-> [Endor Labs] <a href="https://www.endorlabs.com/learn/teampcp-isnt-done" rel="nofollow">https://www.endorlabs.com/learn/teampcp-isnt-done</a><p>-> On March 24, 2026, Endor Labs identified that litellm versions 1.82.7 and 1.82.8 on PyPI contain malicious code not present in the upstream GitHub repository. litellm is a widely used open source library with over 95 million month downloads. It lets developers route requests across LLM providers through a single API.</p>
]]></description><pubDate>Sun, 29 Mar 2026 20:51:23 +0000</pubDate><link>https://news.ycombinator.com/item?id=47567177</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47567177</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47567177</guid></item><item><title><![CDATA[New comment by mrkeen in "A case against currying"]]></title><description><![CDATA[
<p>If you're looking for this argument in a language closer to home, it's basically the opposite of your IDE's style guide:<p>If I write this Java:<p><pre><code>  pair.map((a, b) -> Foo.merge(a, b));
</code></pre>
My IDE flashes up with <i>Lambda can be replaced with method reference</i> and gives me<p><pre><code>  pair.map(Foo::merge);
</code></pre>
(TFA does not seem to be arguing against the idea of partial-function-application itself, as much as he wants languages to be explicit about using the full lambda terms and function-call-parentheses.)</p>
]]></description><pubDate>Sun, 22 Mar 2026 21:22:54 +0000</pubDate><link>https://news.ycombinator.com/item?id=47482290</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47482290</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47482290</guid></item><item><title><![CDATA[New comment by mrkeen in "A case against currying"]]></title><description><![CDATA[
<p>I have a web backend with a top-level server that looks something like:<p><pre><code>  ...

  :<|> collectionsServer compactor env registry
  :<|> queryServer qp sp struc registry warcFileReader logger
  :<|> indexationServer fetcher indexer

  ...
</code></pre>
I.e. a request coming into the top-level server will go into the collections server <i>or</i> the query server <i>or</i> the indexation server.  Each server is further broken down (collections has 4 routes, query has 4 routes, indexation has 5 routes.)<p>So lets try making the the arguments of just the collections server explicit.  (It will take me too long to try to do them all.)<p>You can 'list' collections, 'delete' a collection, merge collectionA into collectionB, or get the directory where the collections live.  So the input (the lambda term(s) we're trying to make explicit) can be () <i>or</i> (collectionName) <i>or</i> (collectionNameA, collectionNameB) <i>or</i> ().<p>In order to put these lambda terms explicitly into the source code, we need to add four places to put them, by replacing collectionsServer with the routes that it serves:<p><pre><code>  ...

  :<|> (       listCollections registry
         :<|> (\collectionName -> deleteCollection env registry collectionName)
         :<|> (\collectionName1 collectionName2 -> mergeInto compactor collectionName1 collectionName2)
         :<|>  getCollectionDir env ) 
  :<|> queryServer qp sp struc registry warcFileReader logger
  :<|> indexationServer fetcher indexer

  ...
</code></pre>
And now you know what explicit lambda terms collectionsServer takes!</p>
]]></description><pubDate>Sun, 22 Mar 2026 21:07:59 +0000</pubDate><link>https://news.ycombinator.com/item?id=47482160</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47482160</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47482160</guid></item><item><title><![CDATA[New comment by mrkeen in "Celebrating Tony Hoare's mark on computer science"]]></title><description><![CDATA[
<p>> The concept as proposed by Hoare is strictly necessary for things like partial relations<p>I read the 'Partial Functional Relationships' section.  There's nothing special there.  It's just structs with nulls.<p>> Polluting every type with it
I think you're reacting to the pollution of the syntax.  Hoare already polluted the semantics: <i>Every type</i> can be null.  You can't even model a NonNull<Spouse> because NonNull itself can be null.</p>
]]></description><pubDate>Wed, 18 Mar 2026 20:12:14 +0000</pubDate><link>https://news.ycombinator.com/item?id=47430827</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47430827</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47430827</guid></item><item><title><![CDATA[New comment by mrkeen in "Celebrating Tony Hoare's mark on computer science"]]></title><description><![CDATA[
<p>> What’s the referent of “my spouse” if I’m unmarried?<p>* It's the same referent as all the other things you don't have.  Your struct has a Spouse, why does it not also have a RivieraChateau, a SantaClaus, BankAccountInSwissFrancs.  If you can answer why you left those out, you know why to leave out Spouse.<p>* Why stick to 0-1 Spouses.  As soon as you do that you're gonna need n Spouses, where some of them will have an ex- flag set, married from&to timestamps.<p>> Is your point here that every pointer type for which this can be the case should include an explicitly typed null value?<p>* It shouldn't make a difference whether it's a pointer or a reference or a value or a class.  If you believe null is one of the Integers, you should also believe that null is one of the ints.  Why should your domain change to accommodate C idioms.</p>
]]></description><pubDate>Wed, 18 Mar 2026 13:21:34 +0000</pubDate><link>https://news.ycombinator.com/item?id=47425484</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47425484</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47425484</guid></item><item><title><![CDATA[New comment by mrkeen in "Celebrating Tony Hoare's mark on computer science"]]></title><description><![CDATA[
<p>> First, the null pointer is essentially inevitable if you want to model the world, which has references (things containing denotations of other things).<p>I took major exception to this.  The real world doesn't have non-things, and references do not demand to refer to non-things.<p>If your domain does actually have the concept of null, just make a type for it.  Then you won't accidentally use a 6 or a "foo" where a null was demanded.</p>
]]></description><pubDate>Wed, 18 Mar 2026 12:36:19 +0000</pubDate><link>https://news.ycombinator.com/item?id=47424974</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47424974</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47424974</guid></item><item><title><![CDATA[New comment by mrkeen in "Methods in Languages for Systems Programming (2023)"]]></title><description><![CDATA[
<p>The benefit of <i>values</i> over <i>classes</i> is that they do not hide machinery.<p>If you x.getY(), is that a member access, a computed value, or a network fetch?  Will it lazy-instantiate a log4j singleton and start spamming my IDE with red text?  I refuse the OO dogma that x should be a black box, and I as the programmer on the outside should not concern myself with its implementation details.<p>Onto TFA's parser example:<p><pre><code>  typedef struct Parser {
      // fields
  } Parser;

  Statement  parser_parse_statement(Parser *p);
  Expression parser_parse_expression(Parser *p);
  void       parser_expect(Parser *p, const char *message);
  void       parser_next(Parser *p);
  TokenKind  parser_current(const Parser *p);
</code></pre>
> It sounds like “data should not have ‘behavior’” is being violated here, no? If not, what’s the difference between this module and a class?<p>Correct.  You can write OO in any language, and this parser hides machinery and is acting like a class, not a value.  Look at those voids - those methods either do nothing, or they modify the insides of the parser.  I certainly can't combine them like I could with values, e.g.:<p><pre><code>  Parser *p = choice (parse_statement, parse_expression);
</code></pre>
The above cannot work - whose internal machinery should <i>choice</i> adopt?<p>It is much easier to parse without hidden machinery.  Combine them like values, e.g.:<p><pre><code>  Parser parser_block   = many (parse_statement);
  Parser parser_sum     = seperateWith (parser_plus, parser_product)
  Parser parser_product = separateWith (parser_times, parser_value)
  Parser parser_value   = choice (parser_literal, parser_variable)
</code></pre>
No voids, no internal machinery, any parser_literal is the exact same thing as any other parser_literal.<p>Then just unhide the internal cursor or success/failure state (or whatever other machinery is hidden in there) and pass them in as values:<p><pre><code>  (result, remainder_string) = run_parser (parser_block, input_string);</code></pre></p>
]]></description><pubDate>Tue, 17 Mar 2026 10:24:13 +0000</pubDate><link>https://news.ycombinator.com/item?id=47410755</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47410755</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47410755</guid></item><item><title><![CDATA[New comment by mrkeen in "Type systems are leaky abstractions: the case of Map.take!/2"]]></title><description><![CDATA[
<p>> just have the take! function return an optional map<p>A map of <i>what</i> ?</p>
]]></description><pubDate>Mon, 16 Mar 2026 08:28:34 +0000</pubDate><link>https://news.ycombinator.com/item?id=47396387</link><dc:creator>mrkeen</dc:creator><comments>https://news.ycombinator.com/item?id=47396387</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47396387</guid></item></channel></rss>