For example, Haskell
has the id
function, Julia has the identity
function, and many questions on SO deal with the identity function. (I suppose in Python you can do lambda x:x
)
I've been busting my brain trying to think of a use case for this function; and I've failed.
What is the purpose of the identity function, and what are its common use-cases?
Remember that in Haskell functions are first class values, and can be used as data the same way as other values, and passed as arguments to other functions. Often you build the functions you really want to use by applying other functions to each other. Occasionally you will find that the function you want to use in a spot happens to be nothing more complicated than id
.
For example, here is a function that negates every second element of a list:
negateEverySecond = zipWith id (cycle [id, negate])
In Julia (in the standard library): A quick grep shows that currently the most prominent use of the identity
function is as the default value of the by
argument for various sorting related functions, such as sort!
, sort
, issorted
, etc.
The by
argument allows to specify a function to extract a sorting key from each object, so that two objects a
and b
are compared according to by(a) < by(b)
rather than a < b
. The identity
function is natural as the default, since identity(a) < identity(b)
is just the same as a < b
.
There is also some internal sorting code that is special-cased for when by
is identity
, which should allow more efficient code for the common case.
id
can be a good place to start when building up functions. For instance,
foldl f init xs = foldr (\x r -> \acc -> r (f acc x)) id xs $ init
chi mentions
type K a = (a -> Int) -> Int
-- factorial, CPS
factCPS :: Int -> K Int
factCPS 0 k = k 1
factCPS n k = factCPS (n-1) (k . (*n))
-- factorial, plain
fact :: Int -> Int
fact n = factCPS n id
This approach is actually closely related to the example I give above; the id
in the definition of foldl
is really just the continuation to use.
fact q
= foldl (*) 1 [1..q]
= foldr (\x r -> \acc -> r (acc * x)) id (build
(\c n -> if q<1
then n
else let go k | k <= q = k `c` go (k+1)
| otherwise = n
in go 1)) 1
-- foldr/build
= (if q < 1
then id
else let go k | k <= q = \acc -> go (k+1) (acc * k)
| otherwise = id = \acc -> acc
in go 1) 1
= (if q < 1
then id
else let go k acc | k <= q = go (k+1) (acc * k)
| otherwise = acc
in go 1) 1
= if q < 1
then 1
else let go k acc | k <= q = go (k+1) (acc*k)
| otherwise = acc
in go 1 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With