Почему нельзя помещать сигнатуры типов в объявления экземпляров в Haskell?

Мне нравится помещать сигнатуры типов для всех определений верхнего уровня в свой код. Однако сигнатуры типов в объявлениях экземпляров кажутся недопустимыми, и если я их поставлю, я получаю сообщение об ошибке «Неуместная сигнатура типа» от GHC. Почему это так? Почему GHC не может проверить, совпадает ли сигнатура типа с ожидаемой, и отклонить (или предупредить), если это не так?


person Prateek    schedule 03.12.2011    source источник
comment
В открывшемся мной тикете SPJ прокомментировал: Я хотел [введите подписи в объявления экземпляров], так что я сделал это в свободную минуту. В настоящее время он установил рубеж на GHC 7.6, хотя есть небольшая вероятность, что он попадет в GHC 7.4. Спасибо, что задали этот вопрос! И спасибо, Дэниел Фишер, за предложение сделать билет.   -  person Dan Burton    schedule 06.12.2011


Ответы (5)


Вы можете добавить подписи типов для экземпляров, используя [новый] - XInstanceSigs, что особенно полезно для переноса переменных типа в область видимости. Дополнительную информацию можно найти в официальные документы.

person crockeea    schedule 29.10.2014

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

class Class a where
    f1 :: a -> a

instance Class Foo where
    f1 = foo_f1

--monomorphic version of f1 for Foo:
foo_f1 :: Foo -> Foo
foo_f1 = ...
person hugomg    schedule 03.12.2011

Большинство других ответов здесь довольно старые ... теперь есть расширение языка:

приклейте следующее вверху файла:

{-# Language InstanceSigs #-}
person JonnyRaa    schedule 14.03.2018

Поскольку подпись является частью определения класса, подпись типа в объявлении экземпляра будет дублированной подписью. Я не думаю, что есть проблема с разрешением дублирования подписей в принципе, но нет никакого преимущества в том, чтобы разрешить их в целом, и их проще запретить. Таким образом, определение языка говорит, что для каждой сущности может быть не более одной сигнатуры типа. Особенность разрешения подписей также в объявлениях экземпляров особо не запрашивалась, поэтому расширения, позволяющего это, нет. Если вы действительно этого хотите, вы можете отправить запрос функции в GHC trac < / а>. Если он вызовет достаточный интерес, он может быть реализован (но я не ожидаю, что спрос будет высоким).

person Daniel Fischer    schedule 03.12.2011
comment
Преимущество будет в том, что GHC проверит подпись - программист может заявить о своей уверенности в сигнатуре типа и проверить ее и поймать в случае, если она неверна. - person Prateek; 03.12.2011
comment
@Prateek Компилятор все равно проверяет его по сигнатуре в классе. Поскольку любая сигнатура, кроме сигнатуры из определения класса (с соответствующими переменными типа, замененными на типы экземпляров), должна быть отклонена, она не может дать никакой дополнительной информации или безопасности. Это была бы лишь небольшая дополнительная документация для читателей кода (это неплохо, но теперь вы можете добиться этого с помощью подписей в комментариях - я делаю это, если считаю, что типы не очевидны и хорошо известны. ). - person Daniel Fischer; 03.12.2011
comment
Я имел в виду проверку того, что программист считает подписью (помимо проверки подписи в классе). Никакой дополнительной безопасности это, правда, не дает. Но он может выдавать более понятные сообщения об ошибках: вы думаете, что сигнатура типа X, но на самом деле это Y, а не какая-то ошибка другого типа. Кроме того, это позволяет программисту принять единый стиль написания объявлений типа вместо того, чтобы делать особый случай его комментирования внутри объявлений экземпляров. - person Prateek; 03.12.2011
comment
@Prateek Я не понимаю, конечно, программист считает, что самый общий тип реализации, по крайней мере, столь же общий, как то, что определяет класс? Можете ли вы привести пример сообщения об ошибке, которое было бы лучше, если бы использовалась прямая подпись, чем с унаследованной? Я не могу придумать такой случай в голове. Однако, если реализация не короткая, хорошей практикой является сделать то, что предложено missingno, определить функцию верхнего уровня и привязать член класса к этому в объявлении экземпляра, почему бы не сделать это также для коротких реализаций? - person Daniel Fischer; 03.12.2011
comment
Я согласен с тем, что единообразие в написании подписей типов - это хорошо, и для этого было бы удобно разрешить подписи в объявлениях экземпляров. Но я считаю, что это не серьезная проблема. - person Daniel Fischer; 03.12.2011
comment
Программисты тоже могут ошибаться. :-) Например, программист может ошибочно подумать, что для того, чтобы сделать что-то T a Functor, нужно определить fmap :: T (a -> b) -> T a -> T b (путать с Applicative) и написать эту сигнатуру типа вместе с некоторой сложной реализацией fmap. Несомненно, сигнатура этого типа неверна, она должна быть такой-то и такой-то! error будет легче понять, чем то, что не может соответствовать bar с foo, ожидаемым baz, фактической ошибкой quux, которая будет сгенерирована. - person Prateek; 03.12.2011
comment
Я согласен с тем, что это не серьезная проблема, поскольку не нарушается безопасность, это скорее проблема более четкого взаимодействия между пользователем и компилятором и возможности принять единый стиль кодирования. Что касается дополнительной функции верхнего уровня, она кажется немного неэлегантной: она вводит ненужное имя в пространство имен верхнего уровня (которое не нужно экспортировать, если это модуль, я согласен), он отделяет реализацию от объявления экземпляра , требует дополнительной работы и внимания, ... - person Prateek; 03.12.2011
comment
@DanBurton Слишком медленно, Prateek подал запрос несколько часов назад :) - person Daniel Fischer; 04.12.2011
comment
@DanielFischer да, похоже, SPJ только что пометил их как подделки друг друга. Есть ли способ объединить билеты? - person Dan Burton; 04.12.2011
comment
@Prateek, я знаю, что это старый, но я решил, что должен упомянуть, что есть довольно много случаев, когда в конечном итоге кому-то все равно нужна дополнительная функция верхнего уровня. В частности, этот подход работает лучше, если вы собираетесь ввести правила перезаписи GHC, соответствующие рассматриваемой функции. - person dfeuer; 07.09.2016

В любом случае тип является избыточным, и обычно требуется избежать дублирования. В Frege, тем не менее, разрешено писать сигнатуры типов для членов экземпляра. Их проверяют, а затем выбрасывают. Их, конечно, проще сразу запретить.

person Ingo    schedule 03.12.2011