<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: Tarean</title><link>https://news.ycombinator.com/user?id=Tarean</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Sat, 18 Apr 2026 00:50:48 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=Tarean" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by Tarean in "We replaced H.264 streaming with JPEG screenshots (and it worked better)"]]></title><description><![CDATA[
<p>Having pair programmed over some truly awful and locked down connections before, dropped frames are infinitely better than blurred frames which make text unreadable whenever the mouse is moved. But 40mbps seems an awful lot for 1080p 60fps.<p>Temporal SVC (reduce framerate if bandwidth constrained) is pretty widely supported by now, right? Though maybe not for H.264, so it probably would have scaled nicely but only on Webrtc?</p>
]]></description><pubDate>Tue, 23 Dec 2025 19:49:43 +0000</pubDate><link>https://news.ycombinator.com/item?id=46368712</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=46368712</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46368712</guid></item><item><title><![CDATA[New comment by Tarean in "Claude Code gets native LSP support"]]></title><description><![CDATA[
<p>Intellij also has structural search and replace, where you can do full subgraph isomorphism search in the code and with patterns like<p><pre><code>    $x$.foo($args$)
</code></pre>
Where you add filters like x's type is a subclass of some class, and args stands for 0-n arguments.<p>You can also access the full intellij API via groovy scripts in the filters or when computing replacement variables, if you really want.<p>Though most of the time built in refactors like 'extract to _' or 'move to' or  'inline' or 'change type signature' or 'find duplicates' are enough.</p>
]]></description><pubDate>Mon, 22 Dec 2025 23:54:57 +0000</pubDate><link>https://news.ycombinator.com/item?id=46360724</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=46360724</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46360724</guid></item><item><title><![CDATA[New comment by Tarean in "GHC now runs in the browser"]]></title><description><![CDATA[
<p>I think WasmGC is very hard to make work with laziness.  
A lazy value is always a closure on the heap.<p>If an expression might be unused, throw a closure which computes it on the heap<p>If the value is actually needed, invoke the closure. Optionally replace the closure with a black hole. A black hole is just a closure which pauses any thread which calls it, to be resumed once the first thread finishes with the expression<p>Once finished, replace with a closure which immediately returns the computation result. (Or often save the indirection because most concrete values also act as closures which immediately returns themselves using info table pointers trickery)<p>Anyway, iirc WasmGC wants very rigid types without dynamic type changes. Extra indirections could fix that, Oor maybe defunctionalizing thunks into a tagged union, but both sound expensive. Especially without being able to hook into the tracing step for indirection removal.<p>Also, Haskell supports finalizers so WasmGC would need that as well.</p>
]]></description><pubDate>Sat, 01 Nov 2025 18:43:50 +0000</pubDate><link>https://news.ycombinator.com/item?id=45784197</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=45784197</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45784197</guid></item><item><title><![CDATA[New comment by Tarean in "John Carmack on mutable variables"]]></title><description><![CDATA[
<p>Sometimes keeping a fixed shape for the variable context across the computation can make it easier to reason about invariants, though.<p>Like, if you have a constraint is_even(x) that's really easy to check in your head with some informal Floyd-Hoare logic.<p>And it scales to extracting code into helper functions and multiple variables. If you must track which set of variables form one context x1+y1, x2+y2, etc I find it much harder to check the invariants in my head.<p>These 'fixed state shape' situations are where I'd grab a state monad in Haskell and start thinking top-down in terms of actions+invariants.</p>
]]></description><pubDate>Fri, 31 Oct 2025 14:06:12 +0000</pubDate><link>https://news.ycombinator.com/item?id=45772126</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=45772126</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45772126</guid></item><item><title><![CDATA[New comment by Tarean in "Recall for Linux"]]></title><description><![CDATA[
<p>I'm pretty sure recall was specifically a selling point for laptops with ai chips which could do the processing locally and reasonably efficiently?<p>Though storing the data locally still could make getting compromised by a targeted attack more dangerous.</p>
]]></description><pubDate>Mon, 27 Oct 2025 13:52:08 +0000</pubDate><link>https://news.ycombinator.com/item?id=45721047</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=45721047</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45721047</guid></item><item><title><![CDATA[New comment by Tarean in "Uncertain<T>"]]></title><description><![CDATA[
<p>Interval arithmetic is only a constant factor slower but may simplify at every step. For every operation over numbers there is a unique most precise equivalent op over intervals, because there's a Galois connection. But just because there is a most precise way to represent a set of numbers as an interval doesn't mean the representation is precise.<p>A computation graph which gets sampled like here is much slower but can be accurate. You don't need an abstract domain which loses precision at every step.</p>
]]></description><pubDate>Thu, 28 Aug 2025 20:54:18 +0000</pubDate><link>https://news.ycombinator.com/item?id=45056929</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=45056929</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45056929</guid></item><item><title><![CDATA[New comment by Tarean in "The Yin and Yang of Programming"]]></title><description><![CDATA[
<p>In my head the two dimensions are tail Vs non-tail jumps, and explicit Vs implicit scope passing.<p>The most interesting case is implicit scope+non-tail recursion, usually this requires you to capture the variable context in mutable objects/monads/effects or similar.<p>This explicit capturing is neat because you still have consistent shapes for your state to define invariants over, but it's easier to decompose the logic and ignore parts of the context which are irrelevant.
It lets you split problems into domain specific languages, each of which has a set of (maybe overlapping) contexts, and ideally each of which can be proven in isolation.<p>Also, the control flow of loops is a very restricted case of even tail jumps. Tail recursion has arbitrary jumps between basic blocks and loops are properly nested basic blocks. Even with labeled breaks, efficiently simulating arbitrary tail recursion without goto is tough. Induction proofs/data flow analysis/abstract interpretation don't care, but I'm not sure it makes proofs <i>easier</i>.</p>
]]></description><pubDate>Fri, 28 Feb 2025 10:32:59 +0000</pubDate><link>https://news.ycombinator.com/item?id=43204044</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=43204044</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43204044</guid></item><item><title><![CDATA[New comment by Tarean in "Flattening ASTs and other compiler data structures (2023)"]]></title><description><![CDATA[
<p>Forgot to mention: In the twee style, the int for the function id contains metadata (is it a unification variable or constant name? how many args does it take?). That way f1(f3(f5(), f7())) would be serialised as something like [1,3,5,7], without even references to other offsets</p>
]]></description><pubDate>Sat, 11 Jan 2025 20:49:21 +0000</pubDate><link>https://news.ycombinator.com/item?id=42668812</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=42668812</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42668812</guid></item><item><title><![CDATA[New comment by Tarean in "Flattening ASTs and other compiler data structures (2023)"]]></title><description><![CDATA[
<p>Twee (an equational theorem prover in Haskell used by quickspec) has an interesting take on this.
Terms are slices of arrays, but you get a normal interface including pattern matching via synonyms.  
It can also be nice to use phantom types of your references (array offsets), so if you project them into flat view types you can do so type safely<p>Requires the language to have something equivalent to pattern synonyms to be as invisible as twee, though.<p>In twee a TermList is a slice of a bytearray (two ints for offset/length plus a pointer).<p>And a term is an int for the function symbol and an unpacked TermList for the arguments.<p>The pattern match synonyms load a flat representation from the array into a view type, and the allocation of the view type cancels out with the pattern matching so everything remains allocation free.<p><a href="https://hackage.haskell.org/package/twee-lib-2.4.2/docs/Twee-Term.html" rel="nofollow">https://hackage.haskell.org/package/twee-lib-2.4.2/docs/Twee...</a></p>
]]></description><pubDate>Sat, 11 Jan 2025 14:40:32 +0000</pubDate><link>https://news.ycombinator.com/item?id=42666175</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=42666175</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42666175</guid></item><item><title><![CDATA[New comment by Tarean in "Weird Lexical Syntax"]]></title><description><![CDATA[
<p>As of python 3.6 you can nest fstrings. Not all formatters and highlighters have caught up, though.<p>Which is fun, because correct highlighting depends on language version. Haskell has similar problems where different compiler flags require different parsers. Close enough is sufficient for syntax highlighting, though.<p>Python is also a bit weird because it calls the format methods, so objects can intercept and react to the format specifiers in the f-string while being formatted.</p>
]]></description><pubDate>Sat, 02 Nov 2024 17:59:01 +0000</pubDate><link>https://news.ycombinator.com/item?id=42027980</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=42027980</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42027980</guid></item><item><title><![CDATA[New comment by Tarean in "Hash Ordering and Hyrum's Law"]]></title><description><![CDATA[
<p>This behaviour was introduced in 3.6 (and made part of the spec in 3.7 iirc)<p>From the python 3.6 change log:<p>New dict implementation¶
The dict type now uses a “compact” representation based on a proposal by Raymond Hettinger which was first implemented by PyPy. The memory usage of the new dict() is between 20% and 25% smaller compared to Python 3.5.<p>The order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon (this may change in the future, but it is desired to have this new dict implementation in the language for a few releases before changing the language spec to mandate order-preserving semantics for all current and future Python implementations; this also helps preserve backwards-compatibility with older versions of the language where random iteration order is still in effect, e.g. Python 3.5).  
(Contributed by INADA Naoki in bpo-27350. Idea originally suggested by Raymond Hettinger.)<p><a href="https://docs.python.org/3.6/whatsnew/3.6.html#new-dict-implementation" rel="nofollow">https://docs.python.org/3.6/whatsnew/3.6.html#new-dict-imple...</a></p>
]]></description><pubDate>Thu, 03 Oct 2024 14:08:14 +0000</pubDate><link>https://news.ycombinator.com/item?id=41730956</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=41730956</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=41730956</guid></item><item><title><![CDATA[New comment by Tarean in "Why Haskell?"]]></title><description><![CDATA[
<p>Either hackernews or autocorrect ate the p, it was supposed to be \p{L} which is a unicode character class.<p>As the other comment mentioned pcre-compatible Regex are a standard, though the pcre spec isn't super readable. There are some projects that have more readable docs like mariadb and PHP, but it doesn't really make sense to repeat the spec in library docs <a href="https://www.php.net/manual/en/regexp.reference.unicode.php" rel="nofollow">https://www.php.net/manual/en/regexp.reference.unicode.php</a><p>There are libraries for pcre2 or gnu regex syntax with the same API if you prefer those</p>
]]></description><pubDate>Fri, 13 Sep 2024 14:53:39 +0000</pubDate><link>https://news.ycombinator.com/item?id=41531793</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=41531793</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=41531793</guid></item><item><title><![CDATA[New comment by Tarean in "Why Haskell?"]]></title><description><![CDATA[
<p>For Regex I like lens-regex-pcre<p><pre><code>    > import Control.Regex.Lens.Text
    > "Foo, bar" ^.. [regex|\p{L}+|] . match
    ["Foo", "bar"]
    > "Foo, bar" & [regex|\p{L}+|] . ix 1 . match %~ T.intersperse '-' . T.toUpper
    "Foo, B-A-R" 
</code></pre>
For web requests wreq has a nice interface. The openssl bindings come from a different library so it does need an extra config line, the wreq docs have this example:<p><pre><code>    import OpenSSL.Session (context)
    import Network.HTTP.Client.OpenSSL

    let opts = defaults & manager .~ Left (opensslManagerSettings context)
    withOpenSSL $
      getWith opts "https://httpbin.org/get"
</code></pre>
There are native Haskell tls implementations that you could plug into the manager config. But openssl is probably the more mature option.</p>
]]></description><pubDate>Fri, 13 Sep 2024 12:32:51 +0000</pubDate><link>https://news.ycombinator.com/item?id=41530615</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=41530615</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=41530615</guid></item><item><title><![CDATA[New comment by Tarean in "Conservative GC can be faster than precise GC"]]></title><description><![CDATA[
<p>Both strategies start from roots (e.g. the stack) and then transitively chase pointers. Any memory reachable this way is live.<p>To do this chasing precisely you need some metadata, saying which fields are pointers vs other data like ints. For OOP languages this metadata is stored with the vtables for objects. For the stack you need similar metadata, at the very least how many pointers there are if you put them first in the stackframe.<p>Not having this metadata and conservatively treating random ints as pointers isn't always catastrophic, but it has some drawbacks. Two big ones:<p>- a moving GC is tough, you  have to update pointers after moving an object but can't risk updating random ints that happen to have that value<p>- You do more work during GC chasing random non-pointers, and free less memory meaning more GC runs<p>Generating ths precise GC metadata for stackframes is sort-of easy.You need specific Safe-Points where all data is at known locations for the GC to work anyway, usually by spilling resgisters to the stack. These GC checkpoints usually coincide with heap allocation, which is why long non-allocating loops can block stop-the-world GC and send other threads into a spin-lock in many GC implementations<p>Maybe a non-precise GC could treat registers as possible pointers and skip spilling to the stack for Safe-Points? There are alternatives to spilling like a precise stack-map for each program instruction (so every instruction is a safe point), but those are expensive to process. Usually only used for debugging or exception handling, not something frequent like GC</p>
]]></description><pubDate>Sat, 07 Sep 2024 13:31:25 +0000</pubDate><link>https://news.ycombinator.com/item?id=41473849</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=41473849</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=41473849</guid></item><item><title><![CDATA[New comment by Tarean in "My Favorite Algorithm: Linear Time Median Finding (2018)"]]></title><description><![CDATA[
<p>But that stores all elements into memory?</p>
]]></description><pubDate>Thu, 25 Jul 2024 12:25:18 +0000</pubDate><link>https://news.ycombinator.com/item?id=41067809</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=41067809</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=41067809</guid></item><item><title><![CDATA[New comment by Tarean in "My Favorite Algorithm: Linear Time Median Finding (2018)"]]></title><description><![CDATA[
<p>Love this algorithm. It feels like magic, and then it feels obvious and basically like binary search.<p>Similar to the algorithm to parallelize the merge step of merge sort.  
Split the two sorted sequences into four sequences so that `merge(left[0:leftSplit], right[0:rightSplit])+merge(left[leftSplit:], right[rightSplit:])` is sorted. leftSplit+rightSplit should be halve the total length, and the elements in the left partition must be <= the elements in the right partition.<p>Seems impossible, and then you think about it and it's just binary search.</p>
]]></description><pubDate>Thu, 25 Jul 2024 12:15:00 +0000</pubDate><link>https://news.ycombinator.com/item?id=41067716</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=41067716</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=41067716</guid></item><item><title><![CDATA[New comment by Tarean in "Understanding React Compiler"]]></title><description><![CDATA[
<p>To me the big winning is that you don't have to memoize transitively. Occasionally someone asks me for help to optimize some react code, and then the dependency array contains some object/callback that has a dependency which has a dependency which wasn't memoized.</p>
]]></description><pubDate>Fri, 28 Jun 2024 14:36:41 +0000</pubDate><link>https://news.ycombinator.com/item?id=40821011</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=40821011</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40821011</guid></item><item><title><![CDATA[New comment by Tarean in "Understanding React Compiler"]]></title><description><![CDATA[
<p>The big problem is that<p>- memoization sometimes crucial for performance.<p>- passing objects and functions around is common.<p>- you cannot compare objects and functions for semantic equality<p>If you wrote larger react apps you almost certainly had to useCallback at some point so that memoization worked, the compiler fixes that.<p>Whenever you construct an object or function the react compiler memoizes on their free variables so pointer equality is sufficient.<p>Though I do think the compiler caches too aggressively, even if there are no free variables and hoisting is sufficient or escape analysis shows it is unnecessary for semantics.</p>
]]></description><pubDate>Fri, 28 Jun 2024 14:25:15 +0000</pubDate><link>https://news.ycombinator.com/item?id=40820897</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=40820897</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40820897</guid></item><item><title><![CDATA[New comment by Tarean in "Terence Tao on proof checkers and AI programs"]]></title><description><![CDATA[
<p>Computer-Checked proofs are one area where ai could be really useful fairly soon. Though it may be closer to neural networks in chess engines than full llm's.<p>You already use tons of solvers because proving everything by hand  is mind numbingly tedious and time consuming, but tactics/solvers really struggle if you throw too many theorems and lemmas at them. Neural nets as search machines to pattern match relevant lemmas fit perfectly.  
Similarly induction and higher order unification are full-on code synthesis where brute-force iterating over all possible syntax trees is really inefficient.<p>And solvers do a backtracking solve anyway, so if the ai returns 95% irrelevant lemmas it doesn't matter. Still would be a dramatic improvement over manually searching for them.<p>Though I'm not convinced that computer checked proofs are necessarily good for communication. There are reasons beside page-count that proofs for human consumption are high-level and gloss over details.</p>
]]></description><pubDate>Tue, 11 Jun 2024 19:10:08 +0000</pubDate><link>https://news.ycombinator.com/item?id=40650202</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=40650202</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40650202</guid></item><item><title><![CDATA[New comment by Tarean in "Monads are like burritos (2009)"]]></title><description><![CDATA[
<p>Lambdas have two hidden features: Variable capture lets you access variables/values from outer scopes, and statements/calling other functions lets you do control flow.<p>Monads are types that let you build chains of lambdas, so you can mix control flow and variable scoping with the some type-specific logic.<p>Async IO/streams/optionals are monads. It's no accident that these could be programmed as nested callbacks/nested loops/nested if statements. That's the nested chain of Monad->lambda->Monad->...<p>Monads work well with syntax sugar (think async/await), and some languages like Haskell can abstract over them in neat ways.</p>
]]></description><pubDate>Sun, 02 Jun 2024 19:49:49 +0000</pubDate><link>https://news.ycombinator.com/item?id=40556764</link><dc:creator>Tarean</dc:creator><comments>https://news.ycombinator.com/item?id=40556764</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=40556764</guid></item></channel></rss>