DateTime.Now or Date.now is referential transparent?
This is one of the controversial topic in a functional programming article in Qiita.
First of all, we must be very careful since the word "referential transparent" is tricky word/concept in a sense, and a prominent discussion exists in
What is referential transparency?
The questioner states:
What does the term referential transparency mean? I've heard it described as "it means you can replace equals with equals" but this seems like an inadequate explanation.
A very typical explanation but the idea that typically leads us misunderstanding is as follows: (#2 answer of the above page by @Brian R. Bondy )
Referential transparency, a term commonly used in functional programming, means that given a function and an input value, you will always receive the same output. That is to say there is no external state used in the function.
Typical claims I always have heard and thought wrong is like this:
In a programming language, Date.now
always returns a different value that corresponds the current time, and according to
given a function and an input value, you will always receive the same output.
therefore, Date.now
is Not referential transparent!
I know some (functional) programmers firmly believe the above claim is trustworthy, however, #1 and #3 answer by @Uday Reddy explains as follows:
Any talk of "referential transparency" without understanding the distinction between L-values, R-values and other complex objects that populate the imperative programmer's conceptual universe is fundamentally mistaken.
The functional programmers' idea of referential transparency seems to differ from the standard notion in three ways:
Whereas the philosophers/logicians use terms like "reference", "denotation", "designatum" and "bedeutung" (Frege's German term), functional programmers use the term "value". (This is not entirely their doing. I notice that Landin, Strachey and their descendants also used the term "value" to talk about reference/denotation. It may be just a terminological simplification that Landin and Strachey introduced, but it seems to make a big difference when used in a naive way.)
Functional programmers seem to believe that these "values" exist within the programming language, not outside. In doing this, they differ from both the philosophers and the programming language semanticists.
They seem to believe that these "values" are supposed to be obtained by evaluation.
Come to think of it, "external state" is also tricky word/concept.
Referential transparency, a term commonly used in functional programming, means that given a function and an input value, you will always receive the same output. That is to say there is no external state used in the function.
Is "current time" "external state" or "external value"?
If we call "current time" is "external state", how about "mouse event"??
"mouse event" is not a state that should be managed by programming context, it's rather an external event.
given a function and an input value, you will always receive the same output.
So, we can understand as follows:
"current time" is neither "input value" nor "external value" nor "external state" and Date.now
always returns the same output corresponds to the on-going event "current time".
If one still insists or want to call "current time" as a "value", again,
- Functional programmers seem to believe that these "values" exist within the programming language, not outside. In doing this, they differ from both the philosophers and the programming language semanticists.
The value of "current time" never exists within the programming language, but only outside, and the value of "current time" outside obviously updates via not programming context but the real-world's time-flow.
Therefore, I understand Date.now is referential transparent.
I'd like to read your idea. Thanks.
EDIT1
In What is (functional) reactive programming?
Conal Elliott @Conal also explains functional-reactive-programming (FRP).
He is the one of the earliest who develops FRP, and explaines like this:
FRP is about - “datatypes that represent a value ‘over time’ “
Dynamic/evolving values (i.e., values “over time”) are first class values in themselves.
In this FRP perspective,
Date
can be seen as a first-class value "over time" that is immutable object on the Time axis..now
is a property/function to address "the current time" within theDate
Therefore
Date.time
returns immutable and referential transparent value that represents our "current time".
EDIT2
(in JavaScript)
referential intransparent function
let a = 1;
let f = () => (a);
input of Function:f
is none;
output of Function:f
depends on a
that depends on a context outside f
referential transparent function
let t = Date.now();
let f = (Date) => (Date.now());
Although, Date
value resides in our physical world, Date
can be seen as an immutable FRP first-class value "over time".
Since Date
referred from any programming context is identical, we usually implicitly may omit Date
as input value and simply like
let f = () => (Date.now());
EDIT3
Actually, I emailed to Conal Elliott @Conal who is one of the earliest developer of FRP. He kindly replied and informed me there's a similar question here.
How can a time function exist in functional programming?
The questioner states:
So my question is: can a time function (which returns the current time) exist in functional programming?
If yes, then how can it exist? Does it not violate the principle of functional programming? It particularly violates referential transparency which is one of the property of functional programming (if I correctly understand it).
Or if no, then how can one know the current time in functional programming?
and, the answer by Conal Elliott @Conal in stackoverflow:
Yes, it's possible for a pure function to return the time, if it's given that time as a parameter. Different time argument, different time result. Then form other functions of time as well and combine them with a simple vocabulary of function(-of-time)-transforming (higher-order) functions. Since the approach is stateless, time here can be continuous (resolution-independent) rather than discrete, greatly boosting modularity. This intuition is the basis of Functional Reactive Programming (FRP).
Edit4 My appreciation for the answer by @Roman Sausarnes .
Please allow me to introduce my perspective for functional programming and FRP.
First of all, I think programming is fundamentally all about mathematics, and functional programming pursuits that aspect. On the other hand, imperative programming is a way to describe steps of machine operation, that is not necessarily mathematics.
Pure functional programming like Haskel has some difficulty to handle "state" or IO, and I think the whole problem come from "time".
"state" or "time" is pretty much subjective entity to us, human. We naturally believe "time" is flowing or passing, and "state" is changing, that is Naïve realism.
I think Naïve realism for "time" is fundamental hazard and reason for all the confusion in programming community and very few discuss this aspect. In modern physics, or even from Newton Physics we treat time in pure mathematical way, so if we overview our world in physics way, nothing should be difficult to treat our world with pure mathematical functional programming.
So, I overview our world/universe is immutable like pre-recorded DVD, and only our subjective view is mutable, including "time" or "state".
In programming, the only connection between the immutable universe and our mutable subjective experience is "event". Pure functional programming language such as Haskell, basically lacks this view, although some insightful researchers including Cornel Elliott proceed FRP, but the majority still think FRP method is still minor or hard to use andm many of them treat mutable state as a matter of course.
Naturally, FRP is the only smart solution and especially Cornel Elliott as a founder applied this philosophical perspective and declare - first class value "over time". Perhaps, unfortunately, many programmers would not understand what he really meant since they are trapped by Naïve realism, and find it difficult to view "time" is philosophically, or physically immutable entity.
So, if they discuss "pure functional" or "referential transparency" for the advantage of mathematical integrity/consistency, to me, "Date.now" is naturally referential transparent within pure functional programming, simply because "Date.time" access a certain point of immutable time-line of immutable universe.
So What About referential transparency in Denotational semantics like @Reddy or @Roman Sausarnes disucusses?
I overview referential transparency in FP, especially in Haskell community is all about mathematical integrity/consistency.
Sure, maybe I could follow the updated definition of "referential transparency" by Haskell community, and practically, we judge the code is mathematically inconsistent if we judge it's not referential transparent, correct?
Actually, again,
How can a time function exist in functional programming?
A programmer questioned as follows:
So my question is: can a time function (which returns the current time) exist in functional programming?
If yes, then how can it exist? Does it not violate the principle of functional programming? It particularly violates referential transparency which is one of the property of functional programming (if I correctly understand it).
Or if no, then how can one know the current time in functional programming?
Consensus
violate the principle of functional programming
= violates referential transparency which is one of the property of functional programming
= Mathematically inconsistent!!
This is our common perception, correct?
In this question, many answered that "function returning the current time" is Not referential transparent especially in the definition of "referential transparency" by Haskell community, and many mentioned it's about mathematical consistency.
However only a few answered that "function returning the current time" is referential transparent, and one of the answer is from FRP perspective by Conal Elliott @Conal.
IMO, FRP, a perspective to handle a time-stream as a first-class immutable value "over time" is a correct manner with mathematical principle like Physics as I mentioned above.
Then how come "Date.now"/"function returning the current time" became referential intransparent by Haskell context?
Well, only explanation I can think of is the updated definition of "referential transparency" by Haskell community is somewhat wrong.
Event-driven & Mathematical integrity/consistency
I mentioned - In programming, the only connection between the immutable universe and our mutable subjective experience is "event" or "Event-driven".
Functional Programming is evaluated in Event-driven manner, on the other hand, Imperative Programming is evaluated by steps/routine of machine operation described in the code.
"Date.now" depends on "event", and in principle, "event" is unknown to the context of the code.
So, does event-driven destroy mathematical integrity/consistency? Absolutely not.
Mapping Syntax to Meaning - indexical(index finger)
C.S. Peirce introduced the term ‘indexical’ to suggest the idea of pointing (as in ‘index finger’). ⟦I⟧ ,[[here]],[[now]] ,etc..
Probably this is mathematically identical concept of "Monad", "functor" things in Haskell. In denotational semantics even in Haskell, [[now]] as the 'index finger' is clear.
Indexical(index finger) is subjective and so is Event-driven
[[I]] ,[[here]],[[now]] ,etc.. is subjective, and again, in programming, the only connection between the immutable objective universe and our mutable subjective experience is "event" or "Event-driven"
Therefore, as long as [[now]] is bind to event declaration of "Event-driven" Programming, the subjective(context dependent) mathematical inconsistency never occurs, I think.
Edit5
@Bergi gave me an excellent comment:
Yes,
Date.now
, the external value, is referentially transparent. It always means "current time".But
Date.now()
is not, it's a function call returning different numbers depending on external state. The problem with the referentially transparent "concept of current time" is that we cannot compute anything with it.@KenOKABE: Seems to be the same case as
Date.now()
. The problem is that it does not mean the current time at the same time, but at different times - a program takes time to execute, and this is what makes it impure.Sure, we could devise a referentially transparent
Date.now
function/getter that always returns the time of the start of the program (as if a program execution was immediate), but that's not howDate.now()/Date.Now
work. They depend on the execution state of the program. – Bergi
I think we need to discuss it.
Date.now
, the external value, is referentially transparent.
[[Date.now]] is as I mention in #Edit4, an indexical(index finger) that is subjective, but as long as it remains in indexical domain (without an execution/evaluation), it is referentially transparent, that we agreed on.
However, @Bergi suggests Date.now()
(with an execution/evaluation) returns "different values" at different times, and which is no longer referentially transparent. That we have not agreed on.
I think this problem he has shown surely but only exist in Imperative Programming:
console.log(Date.now()); //some numeric for 2016/05/18 xx:xx:xx ....
console.log(Date.now()); //different numeric for 2016/05/18 xx:xx:xx ....
In this case, Date.now()
is not referentially transparent, I agree.
However, in Functional Programming/Declarative Programming paradigm, we would never write like the above. We must write this:
const f = () => (Date.now());
and, this f
is evaluated in some "event-driven" context. That is how a Functional-programming code behaves.
Yes, this code is identical to
const f = Date.now;
Therefore, in Functional Programming/Declarative Programming paradigm, Date.now
or Date.now()
(with an execution/evaluation) never has problem to return "different values" at different times.
So, again, as I mentioned in EDIT4, as long as [[now]] is bind to event declaration of "Event-driven" Programming, the subjective(context dependent) mathematical inconsistency never occurs, I think.