frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

Nix Derivation Madness

https://fzakaria.com/2025/10/29/nix-derivation-madness
43•birdculture•1h ago•2 comments

Attention lapses due to sleep deprivation due to flushing fluid from brain

https://news.mit.edu/2025/your-brain-without-sleep-1029
222•gmays•2h ago•68 comments

Sustainable memristors from shiitake mycelium for high-frequency bioelectronics

https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0328965
29•PaulHoule•2h ago•10 comments

Rotating Workforce Scheduling in MiniZinc

https://zayenz.se/blog/post/rotating-workforce-scheduling/
15•mzl•1h ago•1 comments

Nim 2.2.6

https://nim-lang.org//blog/2025/10/31/nim-226.html
59•xz18r•1h ago•13 comments

Wheels for free-threaded Python now available for psutil

https://gmpy.dev/blog/2025/wheels-for-free-threaded-python-now-available-in-psutil
27•grodola•6d ago•2 comments

AMD Could Enter ARM Market with Sound Wave APU Built on TSMC 3nm Process

https://www.guru3d.com/story/amd-enters-arm-market-with-sound-wave-apu-built-on-tsmc-3nm-process/
226•walterbell•12h ago•164 comments

The cryptography behind electronic passports

https://blog.trailofbits.com/2025/10/31/the-cryptography-behind-electronic-passports/
43•tatersolid•4h ago•24 comments

OpenAI Uses Complex and Circular Deals to Fuel Its Multibillion-Dollar Rise

https://www.nytimes.com/interactive/2025/10/31/technology/openai-fundraising-deals.html
215•reaperducer•2h ago•183 comments

John Carmack on mutable variables

https://twitter.com/id_aa_carmack/status/1983593511703474196
297•azhenley•13h ago•368 comments

Affinity Studio now free

https://www.affinity.studio/get-affinity
1129•dagmx•23h ago•732 comments

Immutable releases are now generally available on GitHub

https://github.blog/changelog/2025-10-28-immutable-releases-are-now-generally-available/
50•fastest963•1h ago•21 comments

Git CLI tool for intelligently creating branch names

https://github.com/ytreister/gibr
14•Terretta•2h ago•10 comments

It's the "Hardware", Stupid

https://haebom.dev/archive?post=4w67rj24q76nrm5yq8ep
4•haebom•6d ago•5 comments

Bertie the Brain

https://en.wikipedia.org/wiki/Bertie_the_Brain
61•breppp•1w ago•9 comments

Phone numbers for use in TV shows, films and creative works

https://www.acma.gov.au/phone-numbers-use-tv-shows-films-and-creative-works
243•nomilk•17h ago•125 comments

How the cochlea computes (2024)

https://www.dissonances.blog/p/the-ear-does-not-do-a-fourier-transform
454•izhak•22h ago•139 comments

Ask HN: Who uses open LLMs and coding assistants locally? Share setup and laptop

28•threeturn•2h ago•9 comments

Kimi Linear: An Expressive, Efficient Attention Architecture

https://github.com/MoonshotAI/Kimi-Linear
186•blackcat201•15h ago•33 comments

Result is all I need

https://rockyj-blogs.web.app/2025/10/25/result-monad.html
89•rockyj•6d ago•60 comments

Free software scares normal people

https://danieldelaney.net/normal/
815•cryptophreak•1d ago•528 comments

987654321 / 123456789

https://www.johndcook.com/blog/2025/10/26/987654321/
609•ColinWright•5d ago•100 comments

A Closer Look at Piezoelectric Crystal

https://www.samaterials.com/content/a-closer-look-at-stressed-piezo-crystals.html
40•pillars•1w ago•12 comments

NPM flooded with malicious packages downloaded more than 86k times

https://arstechnica.com/security/2025/10/npm-flooded-with-malicious-packages-downloaded-more-than...
324•jnord•1d ago•234 comments

Affinity, targeting office workers over pros, making pro tools the loss leader

https://tedium.co/2025/10/30/canva-affinity-free-loss-leader-strategy/
53•speckx•3h ago•39 comments

Springs and bounces in native CSS

https://www.joshwcomeau.com/animation/linear-timing-function/
236•feross•2d ago•36 comments

A classic graphic reveals nature's most efficient traveler

https://www.scientificamerican.com/article/a-human-on-a-bicycle-is-among-the-most-efficient-forms...
43•ako•1w ago•39 comments

Debug like a boss: 10 debugging hacks for developers, quality engineers, testers

https://www.ministryoftesting.com/articles/debug-like-a-boss-10-debugging-hacks-for-developers-qu...
9•rosiesherry•56m ago•3 comments

Show HN: Quibbler – A critic for your coding agent that learns what you want

https://github.com/fulcrumresearch/quibbler
89•etherio•14h ago•22 comments

Florian Schneider Collection: Instruments and equipment up for auction

https://www.juliensauctions.com/en/articles/the-florian-schneider-collection-rare-instruments-and...
57•cainxinth•4d ago•13 comments
Open in hackernews

Result is all I need

https://rockyj-blogs.web.app/2025/10/25/result-monad.html
89•rockyj•6d ago

Comments

anon-3988•6h ago
With the ? syntax in Rust results and exceptions are the same thing. I posit that the former is superior. It is unfortunate that results have worse performance but I don't see any reason why. Results that bubbles up all the way ought to be identical to an uncaught exception.
rcxdude•5h ago
Exceptions can tradeoff happy-path performance for more overhead on the slow path. For example, an exception implementation can make it so that callers can assume the 'Ok' result always appears, because an exception causes a seperate unwinding mechanism to occur that walks the stack back, bypassing that entirely. In contrast every caller to a function that returns a Result must have a branch on that result, and this repeats for each part of the callstack.

This also means that exceptions can have stacktraces that only incur a cost on the unhappy path and even only if that exception is uncaught. While if you want a trace for a bad Result you are going to be doing a lot of extra book-keeping that will be thrown away

In general I agree that Results are the better abstraction, but there are sadly some tradeoffs that seem to be hard to overcome.

thinkharderdev•2h ago
This depends a lot of what you are using exceptions for. I think in general the branch on Ok/Err is probably not meaningful performance-wise because the branch predictor will see right through that.

But more generally the happy-path/error-path distinction can be a bit murky. From my days writing Java back in the day it was very common to see code where checked exceptions were used as a sort of control flow mechanism, so you end up using the slow path relatively frequently because it was just how you handled certain expected conditions that were arbitrarily designated as "exceptions". The idea behind Result types to me is just that recoverable, expected errors are part of the program's control flow and should be handled through normal code and not some side-channel. Exceptions/panics should be used only for actually exceptional conditions (programming errors which break some expected invariant of the system) and immediately terminate the unit of work that experienced the exception.

_ZeD_•5h ago
gosh...

        try {
            val user = authService.register(registrationRequest.email, registrationRequest.password)

            return user
        } catch (exception: Exception) {
            // log exception
            throw exception
        }


no, no, no!

the whole point of the exceptions (and moreso of the unchecked ones) is to be transparent!

if you don't know what to do with an exception do NOT try to handle it

that snippet should just be

    return authService.register(registrationRequest.email, registrationRequest.password)
rockyj•5h ago
I agree, this was just a sample code to show how usually imperative if / else / try / catch code is written. What is also possible is we catch the exception, log it and throw another one.
CGamesPlay•5h ago
I'm gonna plug my favorite note on this topic: https://ericlippert.com/2008/09/10/vexing-exceptions/

Both snippets suffer from being too limited. The first, as you point out, catches too many exceptions. But the second.... What happens if the email address is taken? That's hardly exceptional, but it's an exception that the caller has to handle. Your natural response might be to check if the email address is taken before calling register, but that's just a race condition now. So you really need a result-returning function, or to catch some (but probably not all) of the possible exceptions from the method.

noduerme•5h ago
The way I usually structure it is that the only exception would be some type of failure to connect. Any actual error thrown by the service comes back as a result.error, and any failure (like email address taken) comes back as result.fail. This way you can separate it into (1) connection problem, (2) backend error/bug/database offline/etc, (3) both of those are fine but the backend doesn't like the input.
jillesvangurp•5h ago
Since this looks like Kotlin, worth pointing out that there is a kotlin class in the standard library called Result. I've been using that for a few things. One place that I'm on the fence about but that seems to work well for us is using this in API clients.

We have a pretty standard Spring Boot server with the usual reactive kotlin suspend controllers. Our api client is different. We were early adopters of kotlin-js on our frontend. Not something I necessarily recommend but through circumstances it was the right choice for us and it has worked well for us in the last five years. But it was a rough ride especially the first three of those.

As a consequence, our API client is multiplatform. For every API endpoint, there's a suspend function in the client library. And it returns a Result<T> where T is the deserialized object (via kotlinx serialization, which is multiplatform).

On the client side, consuming a result object is similar to dealing with promises. It even has a fold function that takes a success and error block. Basically failures fall into three groups: 1) failures (any 4xx code) that probably indicate client side bugs related to validation or things that at least need to be handled (show a message to the user), 2) internal server errors (500) that need to be fixed on the server, and 3) intermittent failures (e.g. 502, 503) which usually means: wait, try again, and hope the problem goes away.

What I like about Result is making the error handling explicit. But it feels a bit weird to client side construct an Exception only to stuff it into a Result.error(...) instead of actually throwing it. IMHO there's a bit of language friction there. I also haven't seen too many public APIs that use Result. But that being said, our multiplatform client works well for our use.

But I can't expose it to Javascript in its current form; which is something I have been considering to do. This is possible with special annotations and would mean our multiplatform client would be usable in normal react/typescript projects and something I could push as an npm. But the fact my functions return a Result makes that a bit awkward. Which is why I'm on the fence about using it a lot.

So, nice as a Kotlin API but good to be aware of portability limitations like that. You would have similar issues exposing Kotlin code like that to Java.

rockyj•5h ago
Thank you, a very insightful comment :) As a side note, my latest post (on the same website) is on "reactive" Java / suspend functions in Kotlin.
phplovesong•5h ago
This is why Haxe is awesome. You can target a sloppy langauge and still get the benefits os a ML-like typesystem.
paduc•5h ago
For the typescript world, there is neverthrow[0] which offers a similar Result type.

[0]: https://github.com/supermacro/neverthrow

pshirshov•5h ago

  Promise<Result<number, string>>
everywhere or

  type EitherT[F[_], E, A] = F[Either[E, A]]
and then

  def dosomething(): F[String, Number]
?

Isn't this beautiful: https://github.com/7mind/distage-example/blob/develop/bifunc... ?

RedNifre•4h ago
Why does it have Either? Doesn't TypeScript have "A | B" style sum types?
pshirshov•3h ago
Either is biased, union is not.

Probably we should say "union" instead of sum, as typescript unions are not discriminated. string | string in typescript is exactly the same as just string, while Either[String, String] is a type which is exactly a sum of two string types. Plus Either is biased towards R, the happy path value.

pshirshov•5h ago
Ah, Either. Didn't recognize you from the first glance.

Now we need to invent do-notation, higher kinds and typeclasses and this code would be well composable.

tyteen4a03•5h ago
Smells like something that Effect-TS is designed to solve in the TypeScript world.
flaie•5h ago
Good article.

Maybe you could look up the Try monad API (Scala or Vavr works in Java + Kotlin), by using some extra helper methods you can have something probably a little bit lighter to use.

I believe your example would look like the following with the Try monad (in Java):

  public UserDTO register(UserRegistrationRequest registrationRequest) {
    return Try.of(() -> authService.userExists(registrationRequest.email))
      .filter(Objects::isNull, () -> badRequest("user already exists"))
      .map(userId -> authService.register(registrationRequest.email, registrationRequest.password))
      .get();
  }
The login() function would be using the same pattern to call authService.verify() then filtering nonNull and signing the JWT, so it would be the same pattern for both.
lachenmayer•5h ago
Stick your services into the type too, and you have `Effect`[0], the ultimate monad :)

[0]: https://effect.website/

topspin•5h ago
I've been toting around and refining a Result<> implementation from project to project from Java 8 onwards. Sealed classes in 17+ really make it shine.

I wish Oracle et al. had the courage to foist this into the standard library, damn the consequences. Whatever unanticipated problems it would (inevitably) create are greatly outweighed by the benefits.

I've written Pair<> about a dozen times as well.

oweiler•5h ago
Use the builtin Result class and runCatching/fold and be done with it. Yes, it has shortcomings but works well enough in practice.
byteshiftlabs•4h ago
I love how everyone here shares real experience with Kotlin and Result, it’s cool to see different views that actually teach something.
time4tea•4h ago
Result<T> is a built-in in kotlin, but this enforces that the error type is a Throwable

If you fancy that an error could be just a type, not necessarily a Throwable, you might like Result4k - it offers a Result<T,E>

https://github.com/fork-handles/forkhandles/tree/trunk/resul...

disclaimer: I contribute to this.

RedNifre•4h ago
Nice, what's the KMP plan there?

We currently use https://github.com/michaelbull/kotlin-result , which officially should work on KMP, but has some issues.

LelouBil•4h ago
In Kotlin, my go-to library is https://arrow-kt.io/
greener_grass•4h ago
Result is great but it ideally needs extensible union types (polymorphic variants) plus exhaustive pattern matching to work well.
iandanforth•4h ago
Not a fan. Code branches and this is Good Thing(TM). Result violates the single responsibility principle and tries to make what are distinct paths into a single thing. If your language has exceptions and returned values as distinct constructs then obfuscating them with Result means you end up fighting the language which becomes apparent fairly quickly. It's also a frustrating experience to want to interact with returned values directly and constantly have to deal with a polymorphic wrapper.
mpalmer•3h ago

    Result violates the single responsibility principle and tries to make what are distinct paths into a single thing.
You're trying to equate code paths (outcome handling) with values (outcomes), and that seems a more unfortunate category error.
vjerancrnjak•3h ago
I don't see how try-catch promotes single responsibility principle. I feel like this principle is just arbitrary.

If I have Result<Error, Value> and I change the Error, I have to change all places that are using the Error type and tweak the error handling in mapLeft or flatMapLeft.

If I instead raise Error and change it, I have to look at all the places where this error explodes and deal with it, not to mention, most languages won't even give me a compile time warning if I still keep the previous error type.

I agree that if language does not have do-notation, that it's a bit ugly to sprinkle map and flatMap everywhere. Good example of ugliness is https://github.com/repeale/fp-go

I think only an effect system, or a big environment object, places everything at 1 place, and when types change you have 1 place to edit the code. But starting immediately with an effect system (to abstract away control flow) or big env (to lift all ifs up) is premature.

geon•2h ago
There are cases when you need to store the result of a function regardless of if it succeeded or threw. Like if you need to tell the user that an error occurred. In those situations, a `Result` can make a lot of sense.

Arguably, `Result` can also help when it is important that error are dealt with and not just allowed to bubble up.

MangoToupe•1h ago
> Result violates the single responsibility principle and tries to make what are distinct paths into a single thing.

Only in languages that struggle to represent multiple shapes of values with a single type. I don't think I ever want to use a language with exceptions again.

solomonb•36m ago
What language do you use which does not have exceptions?
wsc981•38m ago
I'm also not a fan. Due to your point regarding code branches, but also because I just don't find the code very readable.

I think Result<T> has its use, but I don't think this is a particular great example.

tyleo•3h ago
I always think more languages should support Result… but only to handle expected error states. For example, you may expect that some functions may time out or that a user may attempt an action with an invalid configuration (e.g., malformed JSON).

Exceptions should be reserved for developer errors like edge cases that haven’t been considered or invalid bounds which mistakenly went unchecked.

embedding-shape•3h ago
I usually divide things in "errors" (which are really "invariant violations") and "exceptions". "exceptions", as the name implies, are exceptional, few and when they happen, they're usually my fault, "errors" on the other hand, depending on the user, happens a lot and usually surfaced to the user.
tcfhgj•2h ago
why not divide things into errors and bugs (programming errors)?
sanex•2h ago
Not all exceptional circumstances are bugs
embedding-shape•2h ago
I'm currently working on something that requires a GPU with CUDA at runtime. If something went wrong while initializing the GPU, then that'd be an exceptuion/bug/"programming error" most likely. If the user somehow ended up sending data to the GPU that isn't compatible/couldn't be converted or whatever, then that'd be an user error, they could probably fix that themselves.

But then for example if there is no GPU at all on the system, it's neither a "programming error" nor something the user could really do something about, but it is exceptional, and requires us to stop and not continue.

tyleo•1h ago
That’s interesting. I’d actually consider this a user error because it’s only in the user’s power to fix it.

For example:

1. You’d want to display a message that they need a GPU.

2. Call stack information isn’t helpful in diagnosing the issue.

9rx•1h ago
> If something went wrong while initializing the GPU, then that'd be an exceptuion/bug/"programming error" most likely.

That depends if it is due to the programmer making a mistake in the code or an environmental condition (e.g. failing hardware). The former is exceptional if detected, a bug if not detected (i.e. the program errantly carries on as if nothing happened, much the dismay of the user), while the latter is a regular error.

> But then for example if there is no GPU at all on the system, it's neither a "programming error" nor something the user could really do something about, but it is exceptional

Not having a GPU isn't exceptional in any sense of the word. It is very much an expected condition. Normally the programmer will probe the system to detect if there is one and if there isn't, fall back to some other option (e.g. CPU processing or, at very least, gracefully exiting with feedback on how to resolve).

The programmer failing to do that is exceptional, though. Exceptions are "runtime compiler errors". A theoretical compiler could detect that you forgot to check for the presence of a GPU before your program is ever run.

The grey area is malfunctioning CPU/memory. That isn't programmer error, but we also don't have a good way to think about it as a regular error either. This is what "bug" was originally intended to refer to, but that usage moved on long ago and there is seemingly no replacement.

kubanczyk•1h ago
That's subtly different. It's secondary whose fault is this, what primarily matters is whether you should continue with the rest of the process.

There is always a cleanup layer, the trick is to choose well between 1 and 2:

  1. Some code in the same OS process is able to bring data back to order.

  2. OS can kill the process and thus kill any corruption that was in its address space.

  3. Hardware on/off button can kill the entire RAM content and thus kill any corruption that spilled over it.
Take for example an unexpected divide by zero, that's a classic invariant violation. The entire process should blow up right there because:

- it knows that the data in memory is currently corrupted,

- it has no code to gently handle the corruption,

- and it knows the worst scenario that can happen: some "graceful stop", etc., routine might decide to save the corrupted data to disk/database/third-party. Unrecoverable panic (uncatchable exception) is a very good generic idea, because persistently-corrupted-data bug is a hundred times worse than any died-with-ugly-message bug as far as users are concerned.

9rx•1h ago
Both bugs and exceptions can be reasonably thought of as programmer error, but they are not the same kind of programmer error. Exceptions are flaws in the code — conditions that could have been caught at compile time with a sufficiently advanced language/compiler. Whereas bugs are conditions that are programatically sound, but violate human expectations.
teraflop•1h ago
I find it kind of funny that this is almost exactly how Java's much-maligned "checked exceptions" work. Everything old is new again.

In Java, when you declare a function that returns type T but might also throw exceptions of type A or B, the language treats it as though the function returned a Result<T, A|B>. And it forces the caller to either handle all possible cases, or declare that you're rethrowing the exception, in which case the behavior is the same as Rust's ? operator. (Except better, because you get stack traces for free.)

tyleo•1h ago
You know, I’ve also found this funny.

I like the declaration side. I think part of where it misses the mark is the syntax on the caller side.

I feel like standard conditionals are enough to handle user errors while the heavy machinery of try-catch feels appropriately reserved for unexpected errors.

lock1•49m ago
Probably, the problem with Java's `try-catch` is it's not composable and has an abundance of unchecked exceptions (could mess up `catch` type). In Rust, you could just `?` to short-circuit return or do another chained method call `result.map(...).and_then(...).unwrap_or(...)`.

And more importantly, I don't think there's any JEP trying to improve checked exception handling.

cies•1h ago
Only it is not considered by the type checker. Result brings errors into the realm of properly typed code that you can reason about. Checked exceptions are a bad idea that did not work out (makes writing functional code tedious, messes with control flow, exceptions are not in the type system).
Borealid•59m ago
The only difference between a `fun doThing: Result<X, SomeError>` and a `fun doThing: X throws SomeError` is that with the checked exception, unpacking of the result is mandatory.

You're still free to wrap the X or SomeError into a tuple after you get one or other other. There is no loss of type specificity. It is no harder to "write functional code" - anything that would go in the left() gets chained off the function call result, and anything that would go in the right() goes into the appropriate catch block.

jonhohle•5m ago
I also don’t understand the argument that Result is anything other than a syntactic difference between these ideas.

    final Foo x;
    try {
        x = foo().bar().baz().car();
    } catch (Exception e) {
        x = null;
    }
    return Optional.of(x);

vs.

    let x = foo()?.bar()?.baz()?.car()?;
    Some(x)
Both eat the error. Both wrap the value. The rust is more terse, but the meaning is the same.
pjmlp•54m ago
While Java gets the blame, the concept was already present in CLU, Modula-3 and C++ before Java was even an idea.

I also find a certain irony that forced checked results are exactly the same idea from CS type theory point of view, even if the implementation path is a different one.

CodesInChaos•54m ago
Java's distinction between Runtime and Checked Exception makes sense, and is pretty much the same panic vs Result distinction Rust makes. But Java's execution of the concept is terrible.

1. Checked exception don't integrate well with the type-system (especially generics) and functional programming. It's also incompatible with creating convenient helper functions, like Rust offers on Result.

2. Converting checked exceptions into runtime exception is extremely verbose, because Java made the assumption that the type of error distinguishes between these cases. While in reality errors usually start as expected in low-level functions, but become unexpected at a higher level. In Rust that's a simple `unwrap`/`expect`. Similarly converting a low level error type to a higher level error type is a simple `map_err`.

3. Propagation of checked exception is implicit, unlike `?` in Rust

Though Rust's implementation does have its weaknesses as well. I'd love the ability to use `Result<T, A | B>` instead of needing to define a new enum type.

dwohnitmok•46m ago
Java's checked exceptions experiment was very painful in various ways that directly exposing an error state as part of the return value is not so I wouldn't quite characterize this as "Everything old is new again."

The first big thing is that Java, especially in the days of when checked exceptions were a really big thing and less so in modern Java, was really into a certain kind of inheritance and interface design that didn't play well with error states and focused on the happy path. It is very difficult to make Java-esque interfaces that play well with checked exceptions because they like to abstract across network calls, in-memory structures, filesystem operations, and other side effectful tasks that have very different exception structures. An interface might have a single `writeData` method that might be backed by alternatively a write into an in-memory dictionary, a filesystem key-value store, a stateless REST API, or a bidirectional WebSocket channel which all have wildly different exceptions that can occur.

The second thing is that because checked exceptions were not actual return values but rather had their own special channel, they often did not play well with other Java API decisions such as e.g. streams or anything with `Runnable` that involved essentially the equivalent of a higher-order function (a function that takes as an argument another function). If e.g. you had something you wanted to call in a `Stream.map` that threw a checked exception, you couldn't use it, even if you notated in the enclosing method that you were throwing a checked exception because there was no way of telling `Stream.map` "if the function being `map`ed throws an exception rethrow it" which arose because checked exceptions weren't actual return values and therefore couldn't be manipulated the same way. You could get around it, but would have to resort to some shenanigans that would need to be repeated every time this issue came up for another API.

On the other hand if this wasn't a checked exception but was directly a part o the return value of a function, it would be trivial to handle this through the usual generics that Java has. And that is what something like `Result` accomplishes.

jonhohle•29m ago
IMHO the mapping issue comes from functions not being first class, so all types require Functor-like interfaces which are needlessly verbose. Splitting these is not semantically different than a function that returns a value vs a function that returns a Result.

I have little love for Java, but explicitly typed checked exceptions are something I miss frequently in other languages.

DarkNova6•3h ago
This is really just a syntactical issue. Not one of types or semantics.

Non trivial operations have errors when the happy path fails. And with web apps IO can fail anytime, anywhere for any reasons.

Sometimes you want to handle them locally, sometimes globally. The question is how ergonomic it is to handle this all for a variety of use cases.

We keep reinventing the wheel because we insist that our own use cases are “special” and “unique”, but they really aren’t.

Personally, I think Java’s proposal on catching errors in switches, next to ordinary data is the right step forward.

Monads are great. You can do lots of great things in them, but ergonomic they are not. We should avoid polluting our type systems where possible.

pornel•3h ago
For Turing Complete languages everything is just a syntactical issue (Turing Tarpit).
DarkNova6•3h ago
And syntax is what most programmers will complain about. Even if it makes the wrong code easier to type.
Thorrez•2h ago

    fun register(registrationRequest: UserRegistrationRequest): UserDTO {
        return success(registrationRequest)
            .flatMap { validRequest ->
                throwIfExists(validRequest.email) { authService.userExists(validRequest.email) }
            }.flatMap {
                runWithSafety { authService.register(registrationRequest.email, registrationRequest.password) }
            }.getOrThrow()
    }
There appears to be some useless code there. Why is validRequest.email being passed to throwIfExists twice? Why is throwIfExists implemented to return the email if the following line (runWithSafety) just ignores that returned email and instead gets the email from registrationRequest.email?
Thorrez•2h ago
The imperative code has

    // log exception
which doesn't exist in the Result version.
DrakeDeaton•1h ago
There's certainly situations where this pattern creates some tricky ambiguity, but more often than not Result is quite an ergonomic pattern to work with.

In case it's useful for anyone, here is a simple plug-in-play TypeScript version:

```

type Ok<T = void> = T extends undefined ? { ok: true; } : { ok: true; val: T; };

type Err<E extends ResultError = ResultError> = { ok: false; err: E; };

type Result<T = void, E = ResultError> = { ok: true; val: T; } | { ok: false; err: E | ResultError; };

class ResultError extends Error { override name = "ResultError" as const; context?: unknown; constructor (message: string, context?: unknown) { super(message); this.context = context; } }

const ok = <T = void>(val?: T): Ok<T> => ({ ok: true, val: val, } as Ok<T>);

const err = (errType: string, context: unknown = {}): Err<ResultError> => ({ err: new ResultError(errType, context), ok: false, });

```

```

const actionTaker = await op().then(ok).catch(err);

if (result.ok) // handle error

else // use result

```

I will be forever grateful to the developer first introduced to this pattern!

bmn__•2m ago
This doesn't pass the smell test. Whenever I've seen the Result or Either type, the definition looked different than what you wrote here. I doubt this composes nicely, with Folktale and fp-ts I can be certain.
hotpotat•1h ago
With regard to AI, why not throw this whole article in an .md file and point CLAUDE.md to it? Codex is better at following rules so maybe you’d have more luck with that. But yeah, AI won’t code your way by default. People expect way too much out of the interns, they need direction.
ActionHank•1h ago
This is one of the issues with LLMs in dev IMO.

You either have the case that tech moves on and the LLM is out of date on anything new, so adoption slows or you have tech slowing down because it doesn't work with LLMs so innovation slows.

Either way, it's great if you're working on legacy in known technologies, but anything new and you have issues.

Can I write a spec or doc or add some context MCP? Sure, but these are bandaids.