Использует для функции Haskell ID

Какое использование функции id в Haskell?

9 ответов

Решение

Это полезно в качестве аргумента для функций более высокого порядка (функций, которые принимают функции в качестве аргументов), где вы хотите, чтобы какое-то конкретное значение оставалось неизменным.

Пример 1. Оставьте значение в покое, если оно находится в Just, в противном случае верните значение по умолчанию, равное 7.

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

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

Пример 2: построение функции с помощью сгиба:

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

Мы построили новую функцию f сложив список функций вместе с (.), с помощью id в качестве базового варианта.

Пример 3: базовый случай для функций в виде моноидов (упрощенно).

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

Как и в нашем примере с Fold, функции могут рассматриваться как объединяемые значения с id служит для пустого дела, и (.) как добавить.

Пример 4: тривиальная хеш-функция.

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 требуют хеш-функции. Но что, если ваш ключ уже хэширован? Затем передайте функцию id, чтобы заполнить ее как метод хеширования, с нулевыми накладными расходами.

Если вы манипулируете числами, особенно с помощью сложения и умножения, вы заметите полезность 0 и 1. Аналогично, если вы манипулируете списками, пустой список оказывается весьма удобным. Точно так же, если вы манипулируете функциями (что очень часто встречается в функциональном программировании), вы заметите такую ​​же полезность id,

В функциональных языках функции - это значения первого класса, которые вы можете передать в качестве параметра. Так что одно из самых распространенных применений id появляется, когда вы передаете функцию в качестве параметра другой функции, чтобы сказать ей, что делать. Один из вариантов того, что делать, скорее всего, будет "просто оставить это в покое" - в этом случае вы передаете idв качестве параметра.

Предположим, вы ищете какое-то решение головоломки, в которой вы делаете ход на каждом ходу. Вы начинаете с позиции кандидата pos, На каждом этапе есть список возможных преобразований, которые вы могли бы сделать pos (например, скольжение кусок в головоломке). На функциональном языке естественно представлять преобразования как функции, поэтому теперь вы можете составить список ходов, используя список функций. Если "ничего не делать" является законным ходом в этой головоломке, то вы должны представить это с id, Если вы этого не сделали, то вам нужно было бы рассматривать "бездействие" как особый случай, который работает иначе, чем "делать что-то". Используя id Вы можете обрабатывать все случаи единообразно в одном списке.

Это, вероятно, причина, почему почти все виды использования id существовать. Чтобы справиться с "ничего не делая" равномерно с "делать что-то".

Так как мы находим хорошие приложения id, Здесь есть палиндром:)

import Control.Applicative

pal :: [a] -> [a]
pal = (++) <$> id <*> reverse

Я также могу помочь улучшить ваш счет в гольф. Вместо того, чтобы использовать

($)

Вы можете сохранить один символ, используя идентификатор.

например

zipWith id [(+1), succ] [2,3,4]

Интересный, более чем полезный результат.

Для другого вида ответа:

Я часто делаю это при объединении нескольких функций в композицию:

foo = id
  . bar
  . baz
  . etc

над

foo = bar
  . baz
  . etc

Это облегчает редактирование. Можно делать подобные вещи с другими "нулевыми" элементами, такими как

foo = return
  >>= bar
  >>= baz

foos = []
  ++ bars
  ++ bazs

Представьте, что вы компьютер, то есть вы можете выполнить последовательность шагов. Тогда, если я хочу, чтобы вы оставались в вашем текущем состоянии, но я всегда должен давать вам инструкции (я не могу просто отключить звук и позволить времени пройти), какую инструкцию я вам даю? Идентификатор - это функция, созданная для этого, для возврата аргумента без изменений (в случае предыдущего компьютера аргументом будет его состояние) и для наличия имени для него. Эта необходимость возникает только тогда, когда у вас есть функции высокого порядка, когда вы работаете с функциями без учета того, что внутри них, что заставляет вас символически представлять даже реализацию "ничего не делать". Аналогично 0, рассматриваемый как количество чего-либо, является символом отсутствия количества. На самом деле в алгебре и 0, и id считаются нейтральными элементами операций + и ∘ (состав функции) соответственно, или более формально:

для всех х типа номер:

  • 0 + х = х
  • х + 0 = х

для всех функций типа f:

  • id ∘ f = f
  • f ∘ id = f

Всякий раз, когда вам нужно где-то иметь функцию, но вы хотите сделать больше, чем просто удерживать ее место (например, "undefined").

Это также полезно, как упоминал выше доктор Стюарт (для будущего), когда вам нужно передать функцию в качестве аргумента другой функции:

join = (>>= id)

или как результат функции:

let f = id in f 10

(предположительно, вы отредактируете вышеупомянутую функцию позже, чтобы сделать что-то более "интересное"...;)

Как уже упоминали другие, id является прекрасным заполнителем для тех случаев, когда вам нужна функция где-то.

Другие вопросы по тегам