Referential transparency is a good property for functions that are internal to your program because it makes it easier to understand what code does. Functions that interact with the outside world (for example, with a database) cannot have referential transparency.
Haskell’s core is a purely functional language. But a purely functional program in Haskell is actually just instructions to build a program, and the program that’s built that way has side effects. That’s what the guy IO ()
means: instructions to build a program whose execution has no referential transparency.
Erlang’s project is a good example here. In Erlang, programs are made up of processes that exchange messages. The language of processes has referential transparency, but the way processes exchange messages does not, because when a process sends a message, the recipient observes this action.
There is no referential transparency in a function that records in the database. The "pure functions" are those that do not cause side effects, and recording in the bank is a side effect.
– bfavaretto
Good to know, I was looking for a solution trying to find a Pattern for this but since it is so... in the case of tests then it is always right to simulate this with a mock to ensure its purity. right?
– Henri Cavalcante
Dude, I don’t think I’m an expert on functional programming. I posted the above comment based on what I understand of the concepts, but I think it better to wait for someone with a more consistent answer.
– bfavaretto
What are you testing? A database-altering function will never be pure unless it is a "no-op". At most you can have an idempotent function - which called once or several times returns the same result and/or produces exactly the same side effect. A
update
may be idempotent (or not), but ainsert
never will be. Anyway, if you [dit] your question detailing exactly where you want to go, maybe we can help you. (P.S. shot in the dark: by chance you have a unit test that makes ainsert
, and wants this test to always return the sameid
at every run?)– mgibsonbr
@mgibsonbr actually the question was at the conceptual level itself, to understand how it would work in these cases, so much so that I did not specify the language precisely for this reason. But what you said already helped me a lot to understand how it works. I am learning Haskell now and I come from imperative programming, so everything is still very new to me.
– Henri Cavalcante
The pure "version" of this function, which maintains referential transparency (but completely unviable in practice) would be a function that returns a new database, containing the new data entered, while keeping the original database intact (or, more realistically, returns the instructions for changing the database). And the bank would have to be returned only with argument - if it were created on the hard disk, it would no longer be a pure function.
– fsanches