Basically how FP sells:
def a
1
end
def b
2
end
def c
a + b
end
You see? c = 3! Now try to apply this logic to (real world with effects): def a
(conn: DBConn) => { .... some complex code ... }
end
def b
(conn: DBConn) => { .. another complex code ... }
end
def c
(conn: DBConn) => a(conn) + b(conn)
end
So c = ? Still transparent?We’re talking about something that starts with things like reduce vs. a for loop with mutable variables to accumulate values. Once the language forces you to think in terms of stateful operations to perform even basic tasks, the reflexive tendency is to use mutable state to perform any task. At that point, nobody really knows what a functional does because you have to understand the entire system to know what the output of a function will be.
Besides, it's good practice to limit how widespread side effects are in any program, anyway.
Monads is a nice way to hide state I have to admit, but not because of referential transparency and "reasoning".
Each Haskell monad might have a different implementation of the >>= (bind) operator, which is referentially transparent and which you can easily substitute. The IO monad would be an exception: I believe that one is not referentially transparent and thus cannot be substituted, because it's not implemented in Haskell. You can however imagine that it is a sort of state monad for the external world, but that's a fiction in practice.
(Note: Haskell monads are not "real monads" from category theory, and nor are monads in any other programming language AFAIK... So it's helpful to be very specific about what we're talking about when we use the word "monad" without context. You can implement a monad-like thing using classes in Python or many other languages, but those aren't referentially transparent and aren't typically the monads people are talking about in the context of pure functional programming.)
No, it's not. and a and b are neither in your second example, otherwise they could not produce any result that could be combined with +. Unless `{ .... some complex code ... }` is just `return 42`.
Referential transparency means that we can evaluate the same thing over and over again and getting exactly the same value back. Obviously that does not work with what you have constructed.
It helps when you annotate your examples with return types. That will make things clear very quickly.