Uses for Haskell id function

23,254

Solution 1

It's useful as an argument to higher order functions (functions which take functions as arguments), where you want some particular value left unchanged.

Example 1: Leave a value alone if it is in a Just, otherwise, return a default of 7.

Prelude Data.Maybe> :t maybe
maybe :: b -> (a -> b) -> Maybe a -> b

Prelude Data.Maybe> maybe 7 id (Just 2)
2

Example 2: building up a function via a fold:

Prelude Data.Maybe> :t foldr (.) id [(+2), (*7)]
:: (Num a) => a -> a

Prelude Data.Maybe> let f = foldr (.) id [(+2), (*7)]

Prelude Data.Maybe> f 7
51

We built a new function f by folding a list of functions together with (.), using id as the base case.

Example 3: the base case for functions as monoids (simplified).

instance Monoid (a -> a) where
        mempty        = id
        f `mappend` g = (f . g)

Similar to our example with fold, functions can be treated as concatenable values, with id serving for the empty case, and (.) as append.

Example 4: a trivial hash function.

Data.HashTable> h <- new (==) id :: IO (HashTable Data.Int.Int32 Int)

Data.HashTable> insert h 7 2

Data.HashTable> Data.HashTable.lookup h 7
Just 2

Hashtables require a hashing function. But what if your key is already hashed? Then pass the id function, to fill in as your hashing method, with zero performance overhead.

Solution 2

If you manipulate numbers, particularly with addition and multiplication, you'll have noticed the usefulness of 0 and 1. Likewise, if you manipulate lists, the empty list turns out to be quite handy. Similarly, if you manipulate functions (very common in functional programming), you'll come to notice the same sort of usefulness of id.

Solution 3

In functional languages, functions are first class values that you can pass as a parameter. So one of the most common uses of id comes up when you pass a function as a parameter to another function to tell it what to do. One of the choices of what to do is likely to be "just leave it alone" - in that case, you pass id as the parameter.

Solution 4

Suppose you're searching for some kind of solution to a puzzle where you make a move at each turn. You start with a candidate position pos. At each stage there is a list of possible transformations you could make to pos (eg. sliding a piece in the puzzle). In a functional language it's natural to represent transformations as functions so now you can make a list of moves using a list of functions. If "doing nothing" is a legal move in this puzzle, then you would represent that with id. If you didn't do that then you'd need to handle "doing nothing" as a special case that works differently from "doing something". By using id you can handle all cases uniformly in a single list.

This is probably the reason why almost all uses of id exist. To handle "doing nothing" uniformly with "doing something".

Solution 5

For a different sort of answer:

I'll often do this when chaining multiple functions via composition:

foo = id
  . bar
  . baz
  . etc

over

foo = bar
  . baz
  . etc

It keeps things easier to edit. One can do similar things with other 'zero' elements, such as

foo = return
  >>= bar
  >>= baz

foos = []
  ++ bars
  ++ bazs
Share:
23,254
fjsj
Author by

fjsj

Partner at Vinta Software Studio: www.vinta.com.br

Updated on July 08, 2022

Comments

  • fjsj
    fjsj almost 2 years

    Which are the uses for id function in Haskell?

  • Will Ness
    Will Ness over 9 years
    @MiguelRodrigues here:) <*> reverse suggests instance Applicative ((->) r) where (f <*> g) x = f x (g x) and ($) = (.) so pal x = ((++).id) x (reverse x) = x ++ reverse x. (this shows pal = (++) <*> reverse also works).