Константная функция в Haskell
Функция const
определяется в Prelude как:
const x _ = x
В GHCi, когда я пытался
Prelude> const 6 5 -> Gives 6
Но когда я попробовал
Prelude> const id 6 5 -> Gives 5
Даже после внесения изменений, таких как
Prelude> (const id 6) 5 -> Gives 5
Разве эта функция не должна давать 6
как вывод функции id
имеет тип id :: a -> a
который должен связываться как
Prelude> (const 6) 5 -> Gives 6
Почему функционирует const
вести себя по-другому?
3 ответа
Вы, кажется, думаете, что это эквивалентно const (id 6) 5
, где id 6
оценивается до 6, но это не так. Без этих скобок вы передаете id
функционировать как первый аргумент const
, Итак, посмотрите на определение const
снова:
const x _ = x
Это означает, что const id 6 = id
, Следовательно, const id 6 5
эквивалентно id 5
, что на самом деле 5.
Функции также могут быть параметрами других функций. id становится параметром const.
Что на самом деле делает выражение (const id 6) 5:
(const id 6) 5
(const id _) 5 - захватить первый идентификатор параметра
ID 5
5
Подробнее о том, что на самом деле делают операторы:
Все в паре скобок будет рассматриваться как целое выражение (но это не значит, что оно будет вычислено первым). Например: (карта (1+)), (\ x -> (-) x)
Префиксные операторы связываются сильнее, чем инфиксные операторы
Крайний левый префиксный оператор в выражении будет обрабатываться как функция, которая захватывает параметры (включая другие префиксные операторы) в выражении слева направо до обращений к инфиксным операторам или к концу строки. Например, если вы введете map (+) id 3 const + 2 в GHCi, вы получите сообщение об ошибке "Функция" map "применяется к четырем аргументам...", потому что map захватывает (+), id, 3 и const как параметры перед инфиксным оператором +.
Чак прав, применение функции в Haskell остается ассоциативным, а это означает, что вызов функции, такой как f a b c
эквивалентно (((f a) b) c)
, Помните, что в Haskell вы всегда должны практиковаться в рассмотрении типов функций и пытаться определить, что функция может и не может делать, основываясь на ее типе. Поначалу вы можете ничего не вывести из типа функции, но с большим опытом информация о типе станет необходимой.
Какой тип const
? Войти :t const
в GHCi. Он вернется const :: a -> b -> a
, a
а также b
являются переменными типа, что означает, что const будет принимать аргументы любого типа. Поскольку 1-й и 2-й аргументы имеют разные типы, вы можете передать в функцию практически все:
const 1 2 -- returns 1
const 'a' 1 -- returns 'a'
const [1,2,3] "a" -- returns [1,2,3]
Там могли быть определенные ограничения класса типов для переменных типа const
что бы предотвратить прохождение функций, таких как Num
или же Ord
потому что функция не является экземпляром этих классов типов. Другими словами, функция не ведет себя как число или упорядоченная вещь, поэтому f + g
или же f < g
не имеет смысла. Но const
не имеет ограничений класса типов, которые бы мешали нам передавать функции в качестве аргументов. Помните, что Haskell поддерживает функции высшего порядка? Это означает, что функции Haskell могут принимать и возвращать другие функции. Следовательно:
const (+) (*) -- returns (+)
const head tail -- returns head
const id 2 -- returns id
const
просто игнорирует 2-й аргумент и возвращает то, что было передано в качестве 1-го аргумента, будь то Char, String, Integer, Maybe, [], какой-то очень сложный алгебраический тип данных или даже функция.
Если тип const
является a -> b -> a
Можете ли вы угадать тип const 'a'
не узнав это без ввода :t const 'a'
в GHCi? Чтобы узнать тип const 'a'
, замените тип 1-го аргумента вместо всех переменных того же типа, затем удалите первый аргумент из типа.
a -> b -> a
: оригинальный типChar -> b -> Char
: заменить новый тип в переменных типаb -> Char
: тип новой функции, удалив первый аргумент из объявления типа
Какой тип const id
затем?
a -> b -> a
: оригинальный тип(a -> a) -> b -> (a -> a)
: заменаb -> (a -> a)
: результирующий тип (первый аргумент удален)b -> a -> a
: так же, как и выше,->
оператор является правоассоциативным
Упражнение:
- Попробуйте выяснить мысленно или с ручкой и бумагой, без использования GHCi, какие типы:
const (+)
,const head
,const tail
,const (++)
,const map
- Постарайтесь выяснить, какие аргументы вы бы передали вышеприведенным функциям, чтобы получить конкретное значение.