Я изучаю Haskell из книги Хаттона «Программирование на Haskell» (2-е изд.). В начале гл. 7, «Функции высшего порядка», функция «дважды» определяется как:
twice :: (a -> a) -> a -> a
twice f x = f (f x)
Затем приводится несколько примеров использования, например:
> twice reverse [1,2,3]
[1,2,3]
Затем автор говорит что «тот факт, что реверсирование (конечного) списка дважды не имеет никакого эффекта, фиксируется уравнением дважды reverse = id ...» Когда я запускаю ghci и пишу:
GHCi, version 8.4.4: http://www.haskell.org/ghc/ :? for help
Prelude> :type twice
<interactive>:1:1: error: Variable not in scope: twice
Prelude> twice reverse = id
Prelude> :type twice
twice :: p -> a -> a
Prelude> twice reverse [1,2,3]
[1,2,3]
Фактически это работает как определение функции, поскольку дважды не определено ранее. Теперь мой вопрос, как это работает? дважды обратный просто определен как псевдоним для id ? Но если да, то почему я могу отдельно запрашивать тип дважды ? В каких частях отчета на языке Haskell объясняется этот вид синтаксиса определения функций? Кроме того, почему используется переменная типа p ? Обычно используются a, b et c. .
Edit
Спасибо за полезные ответы и комментарии, пока!
Я просто хочу предоставить немного больше информации по другим вопросам, которые я задал, но которые не были решены. Конечно, на самые важные вопросы уже даны ответы.
Почему одна из переменных типа называется p?
Давайте посмотрим на следующий сеанс ghci:
GHCi, version 8.4.4: http://www.haskell.org/ghc/ :? for help
Prelude> twice asdf fsda = id
Prelude> :type twice
twice :: p1 -> p2 -> a -> a
Prelude> mySum a b c d = a + c
Prelude> :type mySum
mySum :: Num a => a -> p1 -> a -> p2 -> a
Кажется, что p или p1, p2 et c. используются как общие типы c для переменных, которые не используются. Может быть, их тоже используют для других целей. Я нашел подсказку в статье на другом форуме вопросов и ответов. Имена, используемые для переменных типа generi c, могут даже зависеть от реализации c. Важный вывод: неважно, какие буквы используются, потому что важно то, что они отличаются.
Какие части спецификации языка являются соответствующими?
Возможно гл. 4.4.3, «Привязки функций и шаблонов», в отчете о языке 2010 Haskell. Но сейчас для меня это слишком много информации. В конце концов, я где-то в первой половине вводной Haskell книги.