<p>In object-oriented languages, there is typically a notion of object identity which is distinct from object value, such that two objects can have the same values but different identities. For example, in Python this is the distinction between comparisons using <code>is</code> and comparisons using <code>==</code>; in Java it's the distinction between <code>==</code> and <code>.equals()</code>.</p>
<p>However, in pure functional languages, there tends not to be a notion of object identity. Even when a type must necessarily be implemented using references (e.g. a recursive type), the language doesn't have a sense in which two values of that type can be equal but &quot;not the same object&quot;.</p>
<p>Immutability definitely has something to do with it, because two different mutable objects equal by value might not <em>stay</em> equal by value. But object identity is still sometimes a useful concept in object-oriented languages, even for classes that are deeply immutable; for example, &quot;fresh objects&quot; can be used as unique identifiers, or as <a href="https://en.wikipedia.org/wiki/Sentinel_value" rel="noreferrer">sentinel values</a>. Are such use-cases just not useful enough in the functional paradigm to add this as a language feature, or are there concrete reasons why it cannot or should not be implemented? Are there any examples of pure functional languages which do have object identity as a concept?</p>

<functional-programming><value-types>
Why don't pure functional languages have object identity?
CC BY-SA 4.0
2023-06-01T23:40:22.417Z
Reference equality is also often used as a short-circuit when implementing value equality, especially for collections where it’s useful to avoid iteration if possible.
Bbrk24
CC BY-SA 4.0
2023-06-01T23:44:57.253Z
@Bbrk24 True, but the language implementation can do that without exposing it as a language feature.
kaya3
<p>In a pure functional language, functions are <a href="https://en.wikipedia.org/wiki/Referential_transparency" rel="noreferrer">referentially transparent</a> — that is, any function call should be able to be replaced by its value, and vice-versa, without affecting the semantics of the program, and two calls with the same arguments produce the same result. Allowing (inspectable) object identity breaks this property.</p>
<p>Supposing a function that creates an object:</p>
<pre class="lang-none prettyprint-override"><code>makeObj x = object { x = x }
</code></pre>
<p>In a pure system it must be the case that</p>
<pre class="lang-none prettyprint-override"><code>makeObj 5 == makeObj 5
</code></pre>
<p>is true, and that it remains true even if these two instantiations were widely separated in time or location. If each object creation has a detectably different identity, the program can branch based on those differences, and that property doesn't hold. The same is true for less-direct ways of creating an object.</p>
<p>Visible object identity is just inherently impure, so you won't find pure languages that have it.</p>
<hr />
<p>This is assuming an identity-comparing <code>==</code> operation, but it could also be a key in a map, a piecewise function definition, etc — <em>anything</em> that distinguishes two value-equal objects by identity is going to break transparency. You could construct a function like this:</p>
<pre class="lang-none prettyprint-override"><code>sentinel = makeObj 5
choose v = case v of
             sentinel -&gt; 4.0
             _        -&gt; 5.0

choose sentinel / choose (makeObj 5) == 0.8
choose (makeObj 5) / choose sentinel == 1.25
</code></pre>
<p>with different return values based on whether you pass in <code>makeObj 5</code> or <code>sentinel</code>, but these ought to be equivalent. As soon as identity differences are exposed to the programmer somehow we have this issue unless they're unable to have any effect on behaviour... and then we've lost object identity again.</p>
<hr />
<p>As far as use cases go, using fresh objects for sentinel values in object-oriented languages is really reinventing a functional-programming feature within the object-oriented paradigm. The conventional functional approach to situations where you need sentinel values is an unparameterised algebraic data type value, and a unique singleton object fills somewhat the same niche. The better functional design probably doesn't use objects, so this probably wouldn't be a reason for including identity.</p>
<p>Unique identifiers could be useful, perhaps as something like a capability, but there's not a lot of reason to tie that to identity of other values. Unique identity <em>by creation site in the source code</em> is possible in a pure system and would accommodate that sort of usage, but other ways to obtain them probably fall foul of referential transparency again.</p>

CC BY-SA 4.0
2023-06-01T23:54:47.390Z
2023-06-02T00:59:47.103Z
2023-06-02T00:59:47.103Z
Michael Homer
CC BY-SA 4.0
2023-06-02T00:05:15.257Z
I was thinking of referential transparency but thought that it would still hold, as long as the `==` in the definition means value equality rather than reference equality. Perhaps this still causes problems once you start branching based on reference equality ─ could you give a concrete example of this, e.g. a "pure" function which would return 1 the first time you call it and 2 the second time?
kaya3
CC BY-SA 4.0
2023-06-02T01:00:55.747Z
Here `==` is standing in for *any* way of distinguishing different identities - maybe it's a key in a map or something, but anything you can do that has two value-equal objects able to branch differently has a breach following on from it. I added a function that behaves visibly differently at the value level with two should-be-identical arguments.
Michael Homer
CC BY-SA 4.0
2024-02-25T16:58:01.780Z
"*anything* that distinguishes two value-equal objects by identity is going to break transparency“ – coincidentally (or maybe not so coincidentally), this is also true for object-oriented programming. Objects that respond to the same messages in the same way are indistinguishable, which makes it possible to simulate objects. Inspectable Identity breaks this. This means, for example, any Java program that uses `==` is not object-oriented – an important lesson that is often forgotten when teaching OO using Java.
Jörg W Mittag
# Why don't pure functional languages have object identity?
Posted by: username_0 on 2023-06-01
In object-oriented languages, there is typically a notion of object identity which is distinct from object value, such that two objects can have the same values but different identities. For example, in Python this is the distinction between comparisons using `is` and comparisons using `==`; in Java it's the distinction between `==` and `.equals()`.

However, in pure functional languages, there tends not to be a notion of object identity. Even when a type must necessarily be implemented using references (e.g. a recursive type), the language doesn't have a sense in which two values of that type can be equal but "not the same object".

Immutability definitely has something to do with it, because two different mutable objects equal by value might not *stay* equal by value. But object identity is still sometimes a useful concept in object-oriented languages, even for classes that are deeply immutable; for example, "fresh objects" can be used as unique identifiers, or as [sentinel values](https://en.wikipedia.org/wiki/Sentinel_value). Are such use-cases just not useful enough in the functional paradigm to add this as a language feature, or are there concrete reasons why it cannot or should not be implemented? Are there any examples of pure functional languages which do have object identity as a concept?
**Tags:** functional-programming value-types
> **Comments:**
> **username_1**: Reference equality is also often used as a short-circuit when implementing value equality, especially for collections where it’s useful to avoid iteration if possible.  
> **username_0**: @Bbrk24 True, but the language implementation can do that without exposing it as a language feature.  
---
## 1 answers
### Answer by username_2 on 2023-06-01. Score: 22 | Accepted answer
In a pure functional language, functions are referentially transparent — that is, any function call should be able to be replaced by its value, and vice-versa, without affecting the semantics of the program, and two calls with the same arguments produce the same result. Allowing (inspectable) object identity breaks this property.
Supposing a function that creates an object:
makeObj x = object { x = x }

In a pure system it must be the case that
makeObj 5 == makeObj 5

is true, and that it remains true even if these two instantiations were widely separated in time or location. If each object creation has a detectably different identity, the program can branch based on those differences, and that property doesn't hold. The same is true for less-direct ways of creating an object.
Visible object identity is just inherently impure, so you won't find pure languages that have it.

This is assuming an identity-comparing == operation, but it could also be a key in a map, a piecewise function definition, etc — anything that distinguishes two value-equal objects by identity is going to break transparency. You could construct a function like this:
sentinel = makeObj 5
choose v = case v of
             sentinel -> 4.0
             _        -> 5.0

choose sentinel / choose (makeObj 5) == 0.8
choose (makeObj 5) / choose sentinel == 1.25

with different return values based on whether you pass in makeObj 5 or sentinel, but these ought to be equivalent. As soon as identity differences are exposed to the programmer somehow we have this issue unless they're unable to have any effect on behaviour... and then we've lost object identity again.

As far as use cases go, using fresh objects for sentinel values in object-oriented languages is really reinventing a functional-programming feature within the object-oriented paradigm. The conventional functional approach to situations where you need sentinel values is an unparameterised algebraic data type value, and a unique singleton object fills somewhat the same niche. The better functional design probably doesn't use objects, so this probably wouldn't be a reason for including identity.
Unique identifiers could be useful, perhaps as something like a capability, but there's not a lot of reason to tie that to identity of other values. Unique identity by creation site in the source code is possible in a pure system and would accommodate that sort of usage, but other ways to obtain them probably fall foul of referential transparency again.
> **Comments:**
> **username_0** (2023-06-02): I was thinking of referential transparency but thought that it would still hold, as long as the `==` in the definition means value equality rather than reference equality. Perhaps this still causes problems once you start branching based on reference equality ─ could you give a concrete example of this, e.g. a "pure" function which would return 1 the first time you call it and 2 the second time?  
> **username_2** (2023-06-02): Here `==` is standing in for *any* way of distinguishing different identities - maybe it's a key in a map or something, but anything you can do that has two value-equal objects able to branch differently has a breach following on from it. I added a function that behaves visibly differently at the value level with two should-be-identical arguments.  
> **username_3** (2024-02-25): "*anything* that distinguishes two value-equal objects by identity is going to break transparency“ – coincidentally (or maybe not so coincidentally), this is also true for object-oriented programming. Objects that respond to the same messages in the same way are indistinguishable, which makes it possible to simulate objects. Inspectable Identity breaks this. This means, for example, any Java program that uses `==` is not object-oriented – an important lesson that is often forgotten when teaching OO using Java.  
---
