Я делал свой обычный "Прочитайте главу LYAH перед сном", чувствуя, что мой мозг расширяется с каждым образцом кода. На этом этапе я убедился, что понял основную остроту Haskell, и теперь мне просто нужно было понять стандартные библиотеки и классы классов, чтобы я мог начать писать реальное программное обеспечение.
Итак, я читал главу об аппликативных функторах, когда в книге говорилось, что функции не просто имеют типы, они являются типами и могут рассматриваться как таковые (например, делая их экземплярами классов типов). (- > ) является конструктором типа, как и любой другой.
Мой разум снова взорвался, и я сразу же спрыгнул с кровати, загрузил компьютер, отправился в GHCi и обнаружил следующее:
Prelude> :k (->)
(->) :: ?? -> ? -> *
- Что это значит?
- Если (- > ) является конструктором типа, каковы конструкторы значений? Я могу предположить, но понятия не имел, как определить его в традиционном формате
data (->) ... = ... | ... | ...
. Достаточно легко сделать это с любым другим конструктором типа:data Either a b = Left a | Right b
. Я подозреваю, что моя неспособность выразить это в этой форме связана с чрезвычайно странной сигнатурой типа. - Что я только что наткнулся? Более высокие типы типов имеют добрые подписи, такие как
* -> * -> *
. Подумайте об этом... (- > ) появляется в виде подписи! Означает ли это, что это не только конструктор типов, но и конструктор вида? Связано ли это с вопросительными знаками в сигнатуре типа?
Я где-то читал (желаю, чтобы я смог найти его снова, Google не смог меня) о возможности произвольного расширения систем типов, перейдя от значений, к типам значений, к типам, к сортировкам видов, к чему-то еще Сортов, к чему-то еще что-то elses и т.д. навсегда. Отражено ли это в подписи вида (- > )? Потому что я также столкнулся с понятием куб Лямбды и исчислением конструкций, не затрачивая времени на их исследование, и если я правильно помню, можно определить функции, которые принимают типы и возвращаемые типы, принимают значения и возвращают значения, брать типы и возвращаемые значения и принимать значения, возвращающие типы.
Если бы мне пришлось угадать сигнатуру типа для функции, которая принимает значение и возвращает тип, я бы, вероятно, выразил это следующим образом:
a -> ?
или, возможно,
a -> *
Хотя я не вижу основополагающей непреложной причины, почему второй пример не мог быть легко интерпретирован как функция от значения типа a до значения типа *, где * - всего лишь синоним типа для строки или чего-то еще.
Первый пример лучше выражает функцию, тип которой превосходит подписи типа в моем уме: "функция, которая принимает значение типа a и возвращает то, что не может быть выражено как тип".