Я разрабатываю библиотеку, которая в значительной степени выиграет от использования флага компилятора OverlappingInstances. Но everyone говорит smack об этом расширении и предупреждает об его опасностях. Мой вопрос в том, есть примеры хорошего использования этого расширения в любом месте хакера? Есть ли какое-либо эмпирическое правило о том, как инкапсулировать плохость и правильно использовать расширение?Есть ли хорошие варианты использования OverlappingInstances?
ответ
Возможно, мысленный эксперимент немного устранит это расширение.
Давайте сделаем вид, что мы отбросили ограничение, что функции, определенные с помощью нескольких паттернов, должны находиться в одном месте, чтобы вы могли написать foo ("bar", Nothing) = ...
в верхней части модуля, а затем иметь такие случаи, как foo ("baz", Just x) = ...
в другом месте. На самом деле, давайте пойдем еще дальше, и разрешим, чтобы случаи были определены в разных модулях полностью!
Если вы считаете, что это звучит так, как будто это будет путать и подвергнуть ошибкам использовать, вы правы.
Чтобы восстановить какое-то подобие здравомыслия, мы могли бы добавить некоторые ограничения. Например (га, га), мы могли бы потребоваться следующие свойства для хранения:
- Anywhere используется такая функция, аргументы, приведенные должен соответствовать ровно один шаблону. Все остальное - ошибка компилятора.
- Добавление новых шаблонов (в том числе путем импорта другого модуля) никогда не должно изменять значение допустимого кода - либо выбраны одинаковые шаблоны, либо возникает ошибка компилятора.
Должно быть ясно, что соответствующие простые конструкторы, такие как True
или Nothing
, просты. Мы также можем немного переносить вещи и предположить, что компилятор может устранить пробелы в литературе, например, "bar"
и "baz"
.
С другой стороны, связывание аргументов с узорами, как (x, Just y)
становится неудобно - написание такой картины означает отказ возможность писать картины, как (True, _)
или (False, Just "foobar")
позже, так как это может создать неопределенность. Хуже того, стражники становятся почти бесполезными, потому что им нужны очень общие матчи. Многие распространенные идиомы будут приводить к бесконечным двусмысленным головным болям, и, конечно, писать «дефолтный» всплеск картины совершенно невозможно.
Это примерно такая же ситуация с экземплярами класса типов.
Мы могли бы восстановить некоторую выразительную силу, расслабляя требуемые свойства, как, например:
- Везде используются такая функция, она должна соответствовать по крайней мере один шаблона. Нет совпадений - ошибка компилятора.
- Если функция используется так, чтобы совпадало несколько шаблонов, будет использоваться шаблон наиболее подходящего образца. Если нет уникального наиболее конкретного шаблона, возникает ошибка.
- Если функция используется таким образом, который соответствует общему экземпляру, но может применяться во время выполнения к аргументам, которые будут соответствовать более конкретному экземпляру, это ошибка компилятора.
Обратите внимание, что теперь мы находимся в ситуации, когда простое импортирование модуля может изменить поведение функции, введя в область новый более конкретный шаблон. В сложных случаях, в том числе и с функциями более высокого порядка, могут быть мутные. Тем не менее, во многих случаях проблемы маловероятны - скажем, определение общего падающего шаблона в библиотеке, в то же время позволяя клиентскому коду при необходимости добавлять конкретные случаи.
Вот примерно OverlappingInstances
ставит вас. Как было предложено в приведенном выше примере, если создание новых перекрытий всегда либо невозможно, либо желательно, и разные модули не смогут увидеть разные конфликтующие экземпляры, то это, вероятно, хорошо.
В чем дело, так это то, что ограничения, устраняемые OverlappingInstances
, заключаются в том, что использование классов типов ведет себя разумно в соответствии с предположением «открытого мира» о том, что позже может быть добавлен любой возможный экземпляр. Ослабляя эти требования, вы сами берете на себя это бремя; поэтому подумайте о том, как можно добавить новые экземпляры, и является ли какой-либо из этих сценариев серьезной проблемой. Если вы уверены, что ничто не сломается даже в неясных и коварных угловых случаях, тогда продолжайте использовать расширение.
Большинство людей запрашивают перекрывающиеся экземпляры, потому что они хотят связать с ограничениями вывод, а не тип-направленный вывод. Классы типов были сделаны для вывода с типом, и Haskell не обеспечивает элегантное решение ограничения, ориентированного на ограничение.
Однако вы все еще можете «инкапсулировать добро», используя новые типы. Учитывая следующее определение экземпляра, который склонен к перекрывающихся случаях:
instance (SomeConstraint a) => SomeClass a where ...
Вы можете использовать вместо этого:
newtype N a = N { unN :: a }
instance (SomeConstraint a) => SomeClass (N a) where ...
система типа класса В настоящее время в Haskell имеет правильный тип в соответствии с (т.е. N a
), вместо того, чтобы безвозмездно сопоставлять каждый отдельный тип. Это позволяет вам контролировать область действия экземпляра, поскольку теперь будут совпадать только те вещи, которые завернуты в новый тип N
.
Существует ли теоретическая основа для отсутствия ориентированного на ограничение вывода? –
Это самый ясный и понятный способ, которым я когда-либо читал этот совет. Он должен быть помещен во все учебники. – AndrewC
У меня есть googled «ограничение, связанное с ограничениями», но ничего не получилось. Можете ли вы рассказать о концепции? – CMCDragonkai
OverlappingInstances
позволяет писать много полезных вещей, в противном случае нереализуемых на уровне класса типов, подавляющее большинство из них, хотя может быть реорганизовано использовать одну функциональную зависимость (здесь написано в натуральном полиморфноге стиля)
class TypeEq (a :: k) (b :: k) (t :: Bool) | a b -> t where
typeEq :: Proxy a -> Proxy b -> HBool t
в настоящее время это может быть реализовано (полностью родовым образом) с OverlappingInstance
. Примеры использования включают кодирование Олегом ООП в Haskell. Таким образом, мой один пример хорошего использования OverlappingInstances
является this implementation of TypeEq
from the classic HList paper
Эта конкретная функциональность может быть обеспечена очень тривиальным с поддержкой компилятор (и даже работать в функции типа, а не на уровне fundep) и, таким образом, прикрепляя один модуль с TypeEq где-то мне не кажется так плохо.
Когда я занимаюсь опасным стиркой класса, я часто нахожу поведение IncoherentInstances
(выберите первый соответствующий экземпляр), проще рассуждать и более гибко, и поэтому используйте это, по крайней мере, на исследовательских этапах дизайна. Как только у меня есть что-то, что делает то, что я хочу, я пытаюсь избавиться от расширений, обращая особое внимание на менее хорошо себя (как это).
Обратите внимание, что 'TypeEq' может использоваться из неперекрывающихся экземпляров, поэтому действительно можно выделить использование расширения. Вы не можете использовать его с семействами типов, но это другая проблема. В стороне «IncoherentInstances» грубо означает сбросить треть из «смягченных» свойств в моем ответе. Вместо того, чтобы требовать, чтобы выбор экземпляра был согласованным в отношении фактического использования и жалуясь на двусмысленность, GHC просто пожимает плечами и выбирает, какой экземпляр выглядит лучше всего в то время. Ура! –
- 1. Есть ли хорошие учебники для использования ShareKit?
- 2. WordPress - любые хорошие варианты форума?
- 3. Есть ли хорошие iPhone-ормы?
- 4. Каковы хорошие варианты использования кортежей в C++ 11?
- 5. Есть ли варианты защищенной электронной почты?
- 6. iPad DecimalPad Entry - любые хорошие варианты?
- 7. Что плохого в OverlappingInstances?
- 8. Есть ли хорошие учебники для использования sitemesh в приложении grails?
- 9. Есть ли хорошие примеры хорошего использования ввода-вывода C++
- 10. Есть ли хорошие учебники или примеры использования Java ObjectPool/pool?
- 11. Есть ли какие-либо варианты использования std :: forward с prvalue?
- 12. Есть ли какие-либо варианты использования Task.Delay (-1)?
- 13. Есть ли действительные «варианты использования» для Undefined Behavior?
- 14. WAP: Есть ли хорошие симуляторы?
- 15. Есть ли хорошие тесты Clojure?
- 16. Есть ли хорошие альтернативы WebSVN?
- 17. Есть ли там token_get_all варианты?
- 18. Варианты использования для использования AngularJS и JQuery
- 19. Варианты использования Amazon Lambda
- 20. Любые хорошие варианты размещения Git/Trac?
- 21. Варианты использования mmap
- 22. Быстрые варианты использования опций
- 23. Варианты использования OAuth2.0
- 24. ASP.NET Есть ли хорошие способы разработки Wizards?
- 25. Есть ли хорошие альтернативы для Visio/PowerPoint?
- 26. Есть ли хорошие бесплатные онлайн-футуристики ColdFusion?
- 27. Есть ли хорошие углубленные материалы Ruby OOP?
- 28. Есть ли хорошие файловые серверы js узла?
- 29. Есть ли хорошие браузеры объектов R?
- 30. Есть ли там хорошие библиотеки управления WPF?
Это действительно отличный ответ. –
Согласен. Это проклятый приятный ответ. – MathematicalOrchid