HNHacker News
TopNewBestAskShowJobs

tome

9,242 karma · joined November 30, 2008

submissionscomments
tome··on Algebraic Effects for the Rest of Us
Not sure I follow what you're trying to say. Can you elaborate?
tome··on Algebraic Effects for the Rest of Us
> Equating "algebraic effects" with "continuations" is like saying "if" is just "goto"

Fair enough. But are you responding to something I said? I didn't make that equation.

> The only mystique around algebraic effects is the same mystique there is around monads. I don't know if people have started equating algebraic effects to burritos yet but that's a pretty good way to take something simple and turn it into something confusing.

Ah, are you saying that fundamentally there isn't really much to algebraic effects and they're much simpler than they're made out to be? If so then it perhaps we agree?

tome··on Coalton is an efficient, statically typed Lisp with ideas from Haskell and OCaml
Yes, there's a need for it, and Bluefin provides Modify which allows you to modify a reference to a value in a way that is not observable outside the scope of the capability.

https://hackage-content.haskell.org/package/bluefin-0.6.0.0/...

tome··on Algebraic Effects for the Rest of Us
I was completely baffled by "algebraic effects" for years. They looked far too confusing for me to want to spend my time on them, and took the "Don’t feel like you have to [get curious about them]" approach.

But then at some point it struck me: underlying all these effect systems is just passing stuff in. So I developed my own effect system for Haskell, Bluefin[1], based on capabilities, which means the "capability to perform some effect" is represented by just passing stuff in (that is, a function can do some effect as long as it has been passed the capability to do it).

From this point of view it's hard to understand the excitement over "resume with" and "the part you can’t do with try / catch. It lets us jump back to where we performed the effect, and pass something back to it from the handler". Programming languages have had that feature since forever: a "resumable exception" is a "function call". A dynamically chosen "resumable exception" is the call of a dynamically chosen function, i.e. the argument to a higher order function.

So I don't know why people love the complexity around "algebraic effects". Maybe the mystique has a certain allure. But if you want the most straightforward possible approach I can recommend you try out Bluefin. I'm happy to answer questions on the issue tracker[2].

(Caveat: Bluefin is able to simplify things dramatically by dropping support for "multi-shot" continuations. But mostly you don't want multi-shot continuations.)

EDIT: I was too pessimistic, bazoom42 has noticed this :) https://news.ycombinator.com/item?id=48334067

[1] https://hackage.haskell.org/package/bluefin

[2] https://github.com/tomjaguarpaw/bluefin/issues/new

tome··on Coalton is an efficient, statically typed Lisp with ideas from Haskell and OCaml
It's debatable how much one is willing to describe historical solutions like MTL style to be a "good" solution to this problem (I explained the downsides in my talk "A History of Effect Systems"[1] at Zurihac 2025), but I certainly have no hesitation in describing my capability-based effect system Bluefin[2], as a good solution.

For the channels you describe above the type signature would look like this

    Yield String e1 -> -- stdout
    Await String e2 -> -- stdin
    Yield String e3 -> -- logging
    Network e4 -> -- network
    Database e5 -> -- database
    FileSystem e6 -> -- file system
    Eff es r
Six different capabilities that give you access to six different channels of IO. A "Yield" to which you yield strings to stdout, an "Await" from which you can await strings from stdin, a "Yield" to which you yield log messages, and three abstract effects that allow you to do network, database and file system operations (abstract because I'm not sure exactly how you want them defined, but there's an example of the implementation of a file system effect at https://hackage-content.haskell.org/package/bluefin-0.6.0.0/...).

No problem with combining or untangling monads whatsoever. This is the natural conclusion of galaxyLogic's point: instead of dividing your program into two parts (IO and not IO) you divide it into six parts (or maybe 2^6 parts?) according to which fine grained effects you have in scope.

If you (or anyone) has any questions about Bluefin I'm happy to help. Please feel free to ask here or on the issue tracker[3].

[1] https://www.youtube.com/watch?v=RsTuy1jXQ6Y

[2] https://hackage.haskell.org/package/bluefin

[3] https://github.com/tomjaguarpaw/bluefin/issues/new

tome··on Pope Leo XIV says AI must serve humanity, not the powerful few
[flagged]
tome··on Haskell Foundation 2026 Update
Do GHC2021 and GHC2024 not do what you want?
tome··on Over 97% of the 'Linux' Foundation's Budget Goes Not to Linux
> Obviously nobody needs more than that per year

What's the smallest amount per year you'd say it is obvious that no one needs?

tome··on Maybe you shouldn't install new software for a bit
> > Haskell already passes a type object as an argument to anything which does IO. They don't do it for security. Turns out having pure functions separated from non-pure functions is a beautiful thing.

> But almost nobody uses Haskell

Sad, but true

> partly because of poor ergonomics like this!

I'm somewhat dubious that's the reason, partly because I find such ergonomic excellent! Especially those provided by my capability system Bluefin: https://hackage.haskell.org/package/bluefin

tome··on A couple million lines of Haskell: Production engineering at Mercury
Tracing doesn’t actually require IO, only emitting the traces does, and those two need not be done at the same point.

In any case, anywhere they’re doing HTTP calls they are already threading IO, so they don’t have to pay an additional cost.

tome··on A couple million lines of Haskell: Production engineering at Mercury
Any particular stories illustrating that that you can share?
tome··on Functional programmers need to take a look at Zig
I don't understand why Zig's `Io` is a "monad". In fact I discussed that with the author of this article and the author of Zig here, but no conclusion was reached (https://news.ycombinator.com/item?id=46129568).

But, flipping the script, if you want to see something like Zig's `Io` interface in Haskell then have a look at my capability system Bluefin, particularly Bluefin.IO. The equivalent of Zig's `Io` is called `IOE` and you can't do IO without it!

https://hackage-content.haskell.org/package/bluefin-0.5.1.0/...

Regarding custom allocators and such, well, that could fit into the same pattern, in principle, since capabilities/regions/lifetimes are pretty much the same pattern. I don't know how one would plug that into Haskell's RTS.

tome··on Why I still reach for Lisp and Scheme instead of Haskell
> the programmer can't tell if the program is actually

What do you mean, "can't tell"? If I see this in Python

    (A)(B)(C)
how do I know which of your 9 it means? Well, I'm a Python programmer so I know that it means

    A(B)(C)
which is the function A applied to B, which returns a function that gets applied to C. If you're a Haskell programmer you know that it means the same thing.

I grant you that it is odd to those who are unfamiliar and it took me quite a while to get used to it, but it's much better to write that way in Haskell when writing programs that use higher-order functions.

tome··on Generalised plusequals
In Haskell this list is not well-typed

    l = [1, [2, cat], 4]
There are a few different ways to cook this up. Here's one:

    {-# LANGUAGE TemplateHaskell #-}
    
    import Control.Lens
    
    data Cat = Cat { _age :: Int }
      deriving Show
    makeLenses ''Cat
    
    data Item
      = I Int
      | L [Item]
      | C Cat
      deriving Show
    
    makePrisms ''Item
    
    cat :: Cat
    cat = Cat 3
    
    l :: [Item]
    l = [I 1, L [I 2, C cat], I 4]
    
    l' :: [Item]
    l' = set (ix 1 . _L . ix 1 . _C . age) 9 l
    

    ghci> l'
    [I 1,L [I 2,C (Cat {_age = 9})],I 4]
tome··on Saying goodbye to Agile
Right, some people believe that. But did any of the signatories of the Agile Manifesto?
tome··on Saying goodbye to Agile
I'm curious whether it's the author's contention that the signatories of the Agile Manifesto thought that the ideas they were championing went back only a few years, and they had no idea they went back at least 30. In particular

> All of these things were later claimed as Agile innovations

Are there some references that demonstrate that? [EDIT: that the signatories thought they were their own innovations]

And if so, is that a bad thing? Ideas are repeatedly rediscovered. This article isn't called "Saying goodbye to Royce, Bell and Thayer", and I'm wondering why not.

tome··on Saying goodbye to Agile
> Agile doesn't have that, there is no functional equivelant of "the cake should be moist and rise evenly".

That's not true for the way I understand agile. The way I understand it, the testable outcome is whether the principles of the agile manifesto are satisfied

For example, is your highest priority to satisfy the customer through early and continuous delivery of valuable software? If not then you're not agile.

https://agilemanifesto.org/principles.html

tome··on The Economics of Software Teams: Why Most Engineering Orgs Are Flying Blind
Do you have any recommendations? I find his book Principles of Product Development Flow very interesting.
tome··on Prefer do notation over Applicative operators when assembling records (2024)
Here's a silly but simple example:

    newtype FlippedIO a = MkFlippedIO { runFlippedIO :: IO a }
      deriving Functor
    
    instance Applicative FlippedIO where
      pure = MkFlippedIO . pure
      liftA2 f (MkFlippedIO x) (MkFlippedIO y) =
        MkFlippedIO ((flip . liftA2 . flip) f x y)
    
    data Person = Person String String
      deriving Show
    
    putStrLnFlipped = MkFlippedIO . putStrLn
    
    getLineFlipped = MkFlippedIO getLine
    
    getPerson :: IO Person
    getPerson = runFlippedIO $
      Person
        <$> (putStrLnFlipped "Enter your first name:" *> getLineFlipped)
        <*> (putStrLnFlipped "Enter your last name:"  *> getLineFlipped)
It runs things "backwards":

    ghci> getPerson
    One
    Enter your last name:
    Two
    Enter your first name:
    Person "Two" "One"
tome··on ARC-AGI-3
> ML is trying to replace humans

Are household appliances trying to replace humans?

tome··on The future of version control
It doesn't matter which is which. The resolution will be the same regardless.
tome··on The United States and Israel have launched a major attack on Iran
My answer to that question is context dependent. I don't have a strong objection to Israel occupying 4,000 square metres of Lebanon.

But I think we're established the answer to the question I originally asked. Thanks for participating.

tome··on The United States and Israel have launched a major attack on Iran
Right, OK, I guess if you're complaining about some land about the area of an athletics running track then you are technically correct. I'm not sure that's what people would have understood by tsimonescu's original claim that Israel is occupying parts of Lebanon.

And what exactly is Israel doing there, on that land the size of an athletics track? Something very nefarious?

tome··on The United States and Israel have launched a major attack on Iran
Yeah, that's pretty dumb. It's also not what I said. The original comment is a vague insinuation

> Those who know their history also know that the current American administration is of a kind that usually ascends following the rules, but then never voluntarily leaves power.

and not really becoming of a top level Hacker News post. I requested a clarification from bojan and they did not respond to the request. We're all welcome to make our own interpretation of that.

tome··on The United States and Israel have launched a major attack on Iran
Do you mean with the link to Wikipedia? Could you clarify exactly what part of it backs up your claim?
tome··on The United States and Israel have launched a major attack on Iran
Showing that one's claim is not hollow can be achieved in a variety of ways. A prediction market was just a suggestion of one possibility. I'm open to other ways that bojan can show that their claim isn't just empty venting.
tome··on The United States and Israel have launched a major attack on Iran
The goalpost is "Israel's occupation of ... parts of Lebanon". Do you agree with tsimionescu that Israel occupies parts of Lebanon? Can you back that up?
tome··on The United States and Israel have launched a major attack on Iran
> And the only way to prove you’re serious about this opinion is to gamble on it!

If it's a strong claim it's not much of a gamble, is it? Talk is cheap.

tome··on The United States and Israel have launched a major attack on Iran
Then it's also not a very useful claim to make on Hacker News.
tome··on The United States and Israel have launched a major attack on Iran
Talk is cheap. Are you prepared to put money, or anything valuable, where your mouth is?
← PreviousPage 4 of 34Next →