mapNew :: a -> (a -> b -> c) -> [b] -> [c]
Данная подпись типа, какая функция должна быть mapNew
be?haskell функция данного типа подпись, относящаяся к списку
Я знаю, что тип возврата - это список.
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
Данная подпись типа, какая функция должна быть mapNew
be?haskell функция данного типа подпись, относящаяся к списку
Я знаю, что тип возврата - это список.
Это очень похоже на вопрос о домашнем задании. Если да, я настоятельно рекомендую вам попробовать и ответить на этот вопрос для себя. Сказав это, я проведу вас через то, как я сформулирую ответ на этот вопрос, и, надеюсь, вы получите некоторое представление о том, как вы должны подходить к таким вопросам.
Мы знаем, что mapNew
имеет тип a -> (a -> b -> c) -> [b] -> [c]
. Это очень похоже на существующую функцию Prelude map :: (a -> b) -> [a] -> [b]
. Поэтому мы, вероятно, хотим написать наш ответ в терминах map
.
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f bs = ...
Мы всегда начинаем выписав функцию с аргументами он принимает, так что мы можем увидеть, какие части мы должны работать. Зная, что у нас есть только один a
и нужно всегда передавать его f
для каждого элемента b
в bs
, мы можем добавить предложение where
для этого частичного применения:
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f bs = ...
where fa :: b -> c
fa = f a
Учитывая это, мы можем теперь записать наш ответ с точки зрения map
.
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f bs = map fa bs
where fa :: b -> c
fa = f a
Большинство Haskell программистов упростило бы это определение к:
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f bs = map (f a) bs
так (f a)
именно частично применяется функция fa
. Кроме того, мы можем ЕТ сократить это выражение:
mapNew :: a -> (a -> b -> c) -> [b] -> [c]
mapNew a f = map (f a)
Суть этого ответа заключается в утверждении «Зная, что у нас есть только один a
и нужно всегда передавать его f
для каждого элемента b
в bs
». Откуда я знаю это?
Из-за параметрического полиморфизма мы не можем проверять любые значения типа a
. Это означает, что единственное значение типа a
, которое мы нам предоставили, - это тот, который был передан mapNew
. Далее, поскольку f
принимает один b
и производит один c
, мы знаем, что мы должны сначала получить b
из предоставленного списка, чтобы применить к нему f
. Это именно то, что делает map
, и, частично применяя f
до a
, мы получаем первый аргумент, который мы хотим передать, map
.
Это функция, которая применяет те же 'a' и каждый из' [b] 'к функции, переданной как 2-й аргумент, и производит' [c] '. Таким образом, реализация может быть просто «картой» 'a -> (a -> b -> c) -> b -> c' over' [b] ' – zerkms