Hacker Newsnew | past | comments | ask | show | jobs | submit | HeyImAlex's commentslogin

Do effect systems actually avoid colored functions? Don’t most typed effect systems require the used effects in the signature?


Yes, this article is doing a bad job at explaining why you would want effects, and one of the main advantages is exactly that it becomes part of the type system, essentially coloring every single function with a set of effects it needs to be called. As the article used JavaScript it shows what untyped effects would look like, which in my opinion is awful. If you want to use algebraic effects today, I highly recommend Unison. If you’re on the JVM, Flix is doing major advances with effects!

https://www.unison-lang.org/

https://flix.dev/


When you need to use an effect, you need it in the type. If you directly call a function using some other effect, it propagates into your function. So far, so colourful.

But you can have generic effects. Your arguments and return type can specify "any effect", indicating your function can use a type with any effect safely, or can be used in any effect context safely.

Passing an async value to a function doesn't mean that function must now also be an async function. It can be a "for all effects, do the thing" function. The code duplication problem is gone.


No, they are function colouring. That's the point.

Someone writes a post lamenting red and blue functions, and everyone eats it up.

Substitute colour for something meaningful and the idea becomes idiotic.

"Top level function declares that it is non-blocking, but when I try to call a small blocking function from it, I have to change the declaration to blocking???"

Yes, yes you do.

Total functions can't call non-total functions.

Deterministic functions can't call nondeterministic functions.

Non-IO functions can't call IO functions.


‘Non-IO functions can't call IO functions.’

How do you handle logging then? If f() calls g(), how can I add logging to g() without having to change or recompile f() (and everything in the call stack above it)? ‘You can’t’ is not an acceptable answer.


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))


"You can't" is simpler, because the inevitable reply is "but how do I do actual logging inside g"


"Actual logging" as in direct access to IO?


Yes


Don't declare it as non-logging.


If `left_pad()` calls `send_env_vars()`, how can you add exfiltration to `send_env_vars()` without having to change `left_pad()` to expose the use of the network?

"You can't" should be the ONLY acceptable answer.


You can’t is an acceptable answer. The entitle point of such a feature is to prevent people from doing that.


It seems like it would drive down housing prices, but (given limited zoning) drive up land prices?



In the times of the French Revolution that was enough, but I think technology is obsoleting us there too. If evil oligarch can make a bunker and ten million $100 kill bots, I don’t think the people are rising up unless existence is worse than death, and even then they might not win.


colonial revolutions tended to be fought by those for whom death was preferable to existence. i don't disagree that, in this age, the chance of success is slimmer, and will continue to shrink as such --- there's probably some critical mass of capital fortification which is unpenetrable without worker leverage


Back to feudalism, huh?


No, survival of the fittest. In this case, the people whose ancestors were better at hogging resources.


Survival of the shittiest?


Most of human history has been Survival of the Shittiest.


Here’s my favorite post on the subject https://adam-p.ca/blog/2025/04/string-length/


Finally an article that doesn't pretend grapheme clusters are the be-all end-all of Unicode handling.

I'm saving this one. Not exactly how I'd explain it, but it's simplified enough to share with my current co-workers without being misleading.


Another thing I’ve encountered with tree/structured diffs is a concept of identity. diff([{id:1,name:foo}],[{id:2,name:foo}] should show object w/ id:1 removed and id:2 added, not id changed from 1 to 2. Tough because then your diffing algo needs to be aware of the object structure (imo using convention and saying “no objects can contain this key” is pretty tough when you accept any user generated data).


tho i would say that a diff has to define the set of operations allowed to be done to the thing being diff'ed.

E.g., in the example scenario of the diff in json objects, if a possible operation is a change in a property value (such as the "id" field), then the diff correctly deduced the smallest change possible is indeed a change in the field.

However, if you can define the set of operation to only be a change in an entire object (and no changing of id field), then surely, you can create a diff that produces the desired object structure change. It would be a custom diff algorithm of course...but it'd be quite a useful one tbh.


I think his point was that different fields should be treated differently. I.e. if you have two objects with the same ID but different descriptions then you can assume that it's the same object but with a changed description; but if you have two objects with different IDs but the same description then you should assume that the new object is completely different and the identical description is coincidental.

I don't agree that these are always the correct interpretations though. IDs could be reused (especially in a DVCS) or mistaken IDs could be corrected. This ambiguity is a fundamental limitation of the entire concept of diffing, that is reconstructing a set of operations to go from one state to another - you simply don't have the information to deduce the correct logical steps in all cases.


I love this. I think you could simplify it by generalizing. Something like immutability. These keys can’t be changed, only an object destroyed and another created. A case of that is a primary key (maybe that’s the only case).

You can always represent a change as a removal and an addition. It’s smart to actually consider when should you. “Never” and “whenever possible” don’t seem like the best answers.


I think if this can keep a knife effectively sharper than the equivalent nice steel with less maintenance, then it’s going to find a market.

I’m a nerd, but Ive found that once I’ve mastered a hobby I eventually gravitate towards convenience, optimizing my time over absolute performance. I’ve built five PCs in my life, and now I only own a macbook. I spent loads of time optimizing my hifi setup, and now most of my apartment is sonos. And I have probably 1k worth of nice japanese knives + whetstones, that I would happily replace with a single knife that needs little to no upkeep.


I am like you, but my concern with this knife is lifespan. My Japanese knives will last a lifetime. This knife has no warranty that I could find, but how long do we expect it to live? If it’s 10 years or so, I could be happy with it.


Reddit’s eventual livelihood would be based on selling ads, so legality is not the line they were aiming for.


Hasn't the proliferation of streaming services shown that the content is the "drug"? To remain competitive, they had to start producing themselves.


There is value both upstream and downstream


Check out design within reach. Fancy furniture can be incredibly expensive.


Just “made as if it’s not supposed to be replaced every five years” can bump the price of a sofa way higher than $500.

Doesn’t need to be $14k, but probably $4k bare minimum, without paying a premium for a brand name or anything like that, nor going with leather.

The cheaper ones almost always use low-density foam that compresses badly with use in a couple years (IKEA is a big exception here! But also most of their sofas are more than $500…), frames that start to get iffy in a few years, and upholstery that looks ratty after a similar amount of time.


Apparently it’s not within reach for most people?


Furniture is on my list of things where there used to be a range of "solid, and you can make some choices" that was accessible to a lot of people, that has turned into "you can get whatever you want as long as it's made of particle board and laminate and will have a very finite lifetime." Because the old "solid and you can make some choices" zone is mostly upper middle class plus now. (Naming of that site aside.)


Thank you for writing this! It’s something I’ve always wanted a comprehensive guide on, now I have something to point to.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: