HNHacker News
TopNewBestAskShowJobs

tome

9,242 karma · joined November 30, 2008

submissionscomments
tome··on How to earn a billion dollars
Yeah, it should be about the value everyone gets from billionaires. I would love there to be more billionaires. It would be a sign that more and more wealth is being created in society. More billionaires should exist!
tome··on How to earn a billion dollars
Oh, I don't know any of those. The only billionaires I know of are those providing service to consumers or businesses that people can freely decide whether to pay for or not. I just subscribed to another thing on Amazon for far less in price than the value I get for it. Thanks Bezos!

The selfish people I know of are politicians and online commenters who think they're entitled to the wealth built by other people.

tome··on How to earn a billion dollars
I fear you are right, but I feel like trying it anyway.
tome··on How to earn a billion dollars
> Once they define it as stealing, then it's morally indefensible, by definition.

Right, similar to the equivocation around the meaning of earn in this thread. I've started to wonder whether it's possible to push by accepting that framing and then asking for a justification rather than quibbling about what "stealing" is.

tome··on How to earn a billion dollars
Yeah I was more interested in why you haven't saved a baby's life for $4000. Maybe I'm being presumptuous, but even if you don't have $4000 in savings and liquid investments you could probably get a loan for $4000, or extend your mortgage. A baby is going to die if you don't.
tome··on How to earn a billion dollars
Why haven't you saved a baby's life?
tome··on How to Earn a Billion Dollars
How many would it be?
tome··on How to earn a billion dollars
Do you have a want to please millions of people whose lives are improved by exactly the product that your company sells? I could certainly do without that, but it does sound nice.
tome··on How to earn a billion dollars
Sadly, I don't believe that many college grads reasonably well educated in anything other than a scientific field understand exponentials.
tome··on How to earn a billion dollars
What's morally indefensible about that?
tome··on How to earn a billion dollars
What AOC is trying to do here is shift the debate from extracting retribution on people who have violated specific laws (a fair and an honest way to enforce justice in a civil society) to extracting retribution on people who she insinuates "must have done something immoral" based on their net worth (a selfish, dishonest, envious and greedy way to run a society). It's a clever play, and unfortunately for the people of the world who value freedom and a high standard of living, it's going to work. There is enough of the population filled with envy and greed that they'll lap up whatever a politician tells them bogie man of the day is. Historically it's been the aristocracy, Jews, immigrants, but those don't work any more, so now it's generally "the rich". Billionaires are the thin end of the wedge. After them it will be business owners of all kinds, people with second homes, people who send their children to private schools, and generally anyone who has anything else that someone might envy. It's clear that the way society is going people are going to keep lapping this stuff up.

HN used to be open minded about people creating wealth. The change is shocking to me, actually.

tome··on "Don't You Just Upload It to ChatGPT?"
Silly question, but if you don’t look at the code, how do you know if the test is implemented?
tome··on Algebraic Effects for the Rest of Us
Ah yes, OK, I missed the point that the timeout is applied to the entire continuation, not just the part of the computation until the next await. Bluefin can't currently do that. I think I could make it do that, using the same implementation strategy as awaitYield (fork a thread, communicate through an MVar) but I wonder what the point is, given that Bluefin allows you to run the continuation at most once. Is the use case of "run the continuation in a modified environment (e.g. with a timeout)" really that compelling? Maybe it is! But I don't see it yet.

On the other hand, I don't see any difficulty with implementing a scheduler using Await/Yield. I don't think it needs access to the full continuation.

tome··on Algebraic Effects for the Rest of Us
Thanks! This begins to make more sense to me

> effects are handled by handlers

OK, and in the general case a handler allows its body to "perform" an action, and when the action is performed it has the ability to "respond" to it in (in some cases) a very flexible way, running it never, or multiple times, or in a modified environment, or possibly even passing it out of the scope of the handler entirely.

> function signatures describe the effects that are used

Would you say this is not possible in an untyped language then?

> effectful code is written in direct style, not monadic style

I don't understand the distinction here

tome··on Algebraic Effects for the Rest of Us
> Example 2.3 in the paper states that IO is an algebraic effect

Oh, I meant what Haskell calls `IO`, which includes the ability to launch threads, use delimited continuation primops, abort the program, communicate with the FFI, and all sorts of other things that I would guess don't have an algebraic presentation.

tome··on Algebraic Effects for the Rest of Us
Ah, thanks, maybe this holds a clue! (Clearly I have been interested in getting to the bottom of this for a while.)

So maybe an "algebraic effect" is one that's isomorphic to a free monad of a functor that itself is an algebraic data type. That seems to give an unambiguous specification for what it means to handle an effect (a natural transformation) and to take a "free product" of effects (sum the functors).

On the other hand I think it would mean that things like Future and general IO wouldn't be algebraic effects.

tome··on Algebraic Effects for the Rest of Us
Right, I understand the history (although I'm not sure I'd say that exception don't compose well) and I understand that "algebraic effects" are an attempt at something better. But I don't understand whether they're something that can be precisely defined or just informal terminology for "a better sort thing for dealing with effects".
tome··on Algebraic Effects for the Rest of Us
It's my belief that all effects can be done with dependency injection in some form, at least, I'm not familiar with ones that can't. Even arbitrary delimited continuations can be implemented by injecting a reference to the continuation prompt on the stack.
tome··on Algebraic Effects for the Rest of Us
Thanks. It says

> Algebraic effects & handlers use a free monad and an interpreter to separate the syntax of effects from their semantics

I'm pretty sure not everybody who works with algebraic effects would say they have to be based on a free monad, so I'm skeptical how definitive this definition is.

tome··on Algebraic Effects for the Rest of Us
Thanks, I definitely feel like I understand monads and their benefits, and even "effects", but I'm not sure what's "algebraic" in "algebraic effects".
tome··on Algebraic Effects for the Rest of Us
Interesting, then I wonder if anyone has distinguished them from continuation "protocols" such as shift/reset and prompt/control. Thanks!

Bringing it back to my original point, I guess I'd say that if you already have function calls, exceptions and threading built in to the language then you don't need perform/resume except in niche cases (multi-shot continuations being the only case I know of, but I don't even know of many applications of those).

tome··on Algebraic Effects for the Rest of Us
> Protocol in a very layman-y "perform is supposed to do this, resume is supposed to do this".

OK, but at the very least it has two primitives "perform" and "resume"? And they're supposed to interact in some particular way?

tome··on Algebraic Effects for the Rest of Us
"Actual logging" as in direct access to IO?
tome··on Algebraic Effects for the Rest of Us
That's very interesting, thanks! It gave me a brainwave and I wondered I could implement that in Bluefin. I'm pretty sure Bluefin's Request[1] is a second class stackful coroutine, and sure enough it turns out to be possible, so I'm pleased about that.

    -- ghci> example
    -- Hello
    -- World
    -- Timed out
    example = runEff $ \io -> awaitYield (receiver io) sender
    
    receiver ::
      (e1 <: es, e2 <: es) =>
      IOE e1 ->
      Await String e2 ->
      Eff es ()
    receiver io a = do
      r1 <- await a
      effIO io (putStrLn r1)
    
      r2 <- await a
      effIO io (putStrLn r2)
    
      mr3 <- timeout io 0 (await a)
      effIO io $ case mr3 of
        Nothing -> putStrLn "Timed out"
        Just r3 -> putStrLn r3
    
    sender ::
      e1 <: es =>
      Yield String e1 ->
      Eff es ()
    sender y = do
      yield y "Hello"
      yield y "World"
      yield y "More"
    
    timeout ::
      e1 <: es =>
      IOE e1 ->
      Int ->
      Eff es r ->
      Eff es (Maybe r)
    timeout io t m = withEffToIO
      (\effToIO -> System.Timeout.timeout t (effToIO (\_ -> useImpl m)))
      io
tome··on Algebraic Effects for the Rest of Us
> They're really just a protocol.

Thanks, that clarifies where you're coming from. Is it possible to specify this protocol somehow, by defining an interface for it? Or by extending lambda calculus with the bits it needs?

(Maybe that's what the Koka folks do in their papers, and if so feel free to say, "yeah read their papers").

tome··on Algebraic Effects for the Rest of Us
I don't think I said they're just continuations. In fact I'm trying to make the point that they're mostly just function calls (and I think in my career I've come across one case where I wanted something beyond function calls (for a constraint solver)). There are "multi-shot" continuations (whether you consider that interface or implementation I don't really mind), which have behaviour than function calls can't express, but I don't know of any algebraic effects beyond that.

What do you think algebraic effects are, if they're not continuations?

EDIT: Ah, based on your comment at https://news.ycombinator.com/item?id=48334737 you might say they're a feature of an intermediate language? So you might take a surface language and "compile to an intermediate language of lambda calculus + algebraic effects", without specifying how that intermediate language is implemented (because it may not even be implemented, per se).

tome··on Algebraic Effects for the Rest of Us
> I dislike the concept of having a second, hidden, control flow that might get sprung up upon function callers, because it has side effects buried in the implementation of a callee that are not defined in the parameters or the returns

You might like my capability-based effect system for Haskell, Bluefin[1], then. If a Bluefin effectful function throws you can see it in the type system. If you want to have the capability to throw, you need to pass in an argument of type Throw. For example here "workWithThrow" can only throw an exception because it is passed the Throw capability.

    workWithThrow  ::
      (e1 :> es) =>
      Throw String e1 ->
      Int ->
      Int ->
      Eff es Int
    workWithThrow t x y = do
      let result = x + y
      when (result > 10) $ do
        throw t "Too big"
      pure result
    
    -- ghci> example
    -- Left "Too big"
    example :: Either String Int
    example = runPureEff $ try $ \t -> do
      workWithThrow t 5 7

[1] https://hackage.haskell.org/package/bluefin
tome··on Algebraic Effects for the Rest of Us
Not sure why people are saying "you can't" when it seems to me the whole point of algebraic effects that you can. You can define g so that it has no ability to do "general IO", all it can do is yield log messages. Then f can call g in a way that turns the log messages into writes to stdout. For example, here's how you would do it in Bluefin:

    type Log = Yield String
    
    -- workWithLogging cannot do arbitrary IO!
    -- All it can do is yield log messages, which
    -- must be processed elsewhere.
    workWithLogging  ::
      (e1 :> es) =>
      Log e1 ->
      Int ->
      Int ->
      Eff es Int
    workWithLogging l x y = do
      yield l ("x was " <> show x)
      yield l ("y was " <> show y)
      let result = x + y
      yield l ("result was " <> show result)
      pure result
    
    -- ghci> example
    -- x was 5
    -- y was 7
    -- result was 12
    -- 12
    example :: IO Int
    example = runEff $ \io -> do
      -- forEach determines how each log message
      -- should be handled.
      forEach
        (\l-> workWithLogging l 5 7)
        (\logMsg -> effIO io (putStrLn logMsg))
tome··on Algebraic Effects for the Rest of Us
I've never understood what's meant by "algebraic" in that sense, or what this algebra of combining effect is. Could you say more, or maybe share a link to a useful reference?
tome··on Algebraic Effects for the Rest of Us
Thanks for your response. Perhaps I'm missing some fundamental things. Could you help?

> A real effect system allows you to do things like NOT continue execution after using the effect

Right, Bluefin's Request allows you to do that too. For example here is an example of handling the request by continuing or not, depending on what the value yielded to the Request is.

    example :: Either String ()
    example = runPureEff $ try $ \ex -> do
      forEach
        ( \r -> do
            request r True
            request r True
            request r False
            request r True
            request r True
        )
        ( \case
            True -> pure ()
            False -> throw ex "Stopped"
        )
> if you "implement" this by using Exceptions, you're not using effects at all, just using Exceptions with extra steps

Not sure I follow that. Above you can see I used an exception (Bluefin's Throw capability), but I couldn't have used only an exception because that would have aborted unconditionally. What am I missing here, that makes "using Exceptions" "not using effects at all"?

> only continuing it after some asynchronous work happens (the Future effect)

I'm not really sure what "a Future effect" is, but I don't see how it's not something that can be run as a function call, at least in Haskell.

> or even "continue" execution several times

Right, these are the multishot continuations which Bluefin doesn't support. I haven't discovered many particularly compelling use cases for multishot continuations but would be very interested in finding some. The developer of the Kyo effect system for Scala, Flavio Brasil, suggested parsing, with multiple parse results, which makes sense.

I'm also not entirely sure Bluefin couldn't simulate common use cases of multishot continuations with threads, but I haven't thought about it very hard.

> You still don't seem to have understood effects.

Possibly true, and part of my puzzlement! I'm always happy to try to improve my understanding. Can you help me see what I've missed?

← PreviousPage 3 of 34Next →