3 ms·
Ok, the point about special syntax is fair, but as I said, I'm happy with the use cases that have trickled down to mainstream, and I'd argue there aren't _that_
by mpartel 9y ago
Ok, the point about special syntax is fair, but as I said, I'm happy with the use cases that have trickled down to mainstream, and I'd argue there aren't _that_ many truly useful ones. I realize this is very analogous to how the Go programmer is somehow happy with the few generic collections they are granted :)
Your DI example seems to be an example of my earlier point about "emulating things you could do with side-effects". No HKTs are needed when you just pass an impure side-effectful Logger object. Or, as discussed in another subthread, you could do side-effect management with Rust-style uniqueness typing, which results in a less elegant but arguably easier to use type system. It's debatable, but it seems people struggle less with the borrow checker than with advanced Haskell.
- willtim 9y agoI don't see how passing in a logger object explicitly is the same, this is what OO DI frameworks try to avoid, otherwise you'd also have to pass it down to other functions used inside. The example above works just like a Reader Monad, but we are not tied to any specific logging implementation. I guess the side effecting version is just to use some global registry to look up the logging implemention to use. But such code does not compose.
- mpartel 9y agoLooks like we reached maximum thread depth so replying here. I agree, the side-effectful choices are either a global, some DI container, or just passing it down. For loggers, I think global lookup from some (pluggable) logging library is justified because logging is probably the most ubiquitous cross-cutting concern ever. For pretty much everything else, I think passing as a parameter is actually the best option. It's explicit and simple, and you don't even need to explicitly pass it around _that_ much if you store it in a field of a class that plays the role of a module. Most uses of the dependency will be in non-static methods, lambdas, or inner classes. I dislike Reader because it's similar to a DI container (or a global) in that it's more work to figure out, for a given call site, what the last value written to it was. With parameters, you just climb the call chain.