|
|
|
|
|
by hota_mazi
3553 days ago
|
|
> If `function2` needs to log something, then it should have a type signature which reflects that. Yes if you value referential transparency. No if you value encapsulation. The fact that `function2` is logging stuff is an implementation detail that callers shouldn't care about. They should certainly not be forced to pass that function a logger. What if that function decides that on top of logging, it wants to store stuff in a database. Should all callers suddenly find some kind of database to pass to that function too? |
|
On the contrary, I think it definitely matters. If a function is going to log something, I want to know about it. Those logs could cause me problems (e.g. polluting my stdout or attempting to write to a file they don't have permissions on), or I might want to control where those logs go, what the log level is, what the format is, et cetera. This is absolutely something I want to know about.
> What if that function decides that on top of logging, it wants to store stuff in a database. Should all callers suddenly find some kind of database to pass to that function too?
Yes, a thousand times yes. Why would I want a function to be storing stuff in a database without my knowledge? If a function is going to write to a database, it's all the more important that the caller is aware of that. How can I access whatever it stores? How do I know what database it's writing to? How can I be sure that database is properly initialized and/or torn down? How do I know whether the function is threadsafe? How do I know it's a secure connection? Et cetera.
If you want to write a function which does "arbitrary side effects", easy: just write all of your code in the IO monad.
Of course, I don't recommend this...