2012-04-28 3 views
5

Мне очень понравились возражения против implicit parameters, которые обсуждались в статье Functional Pearl: Implicit Configurations Киселева и Шаня.Являются ли неявные параметры трудными для встраивания в GHC?

Это не звук встроенного кода (β-сокращение) при наличии неявных параметров.

Действительно? Я бы ожидал, что GHC должен встроить в ту же область, что и переданный неявный параметр, нет?

Я считаю, что я понимаю их возражение, что:

поведение термина может измениться, если его подпись добавляется, удаляется, или изменен.

документация пользователя GHC объясняет, что программисты должны заботиться вокруг polymorphic recursion и monomorphism restriction. Это как-то то, что они подразумевают под проблемой для встраивания?

Я предполагаю, что этот пример полиморфной рекурсии охватывает то, что они означают, «обобщая также неявные параметры»? Что-нибудь еще?

Является ли класс ReifiesStorable от Data.Reflection действительно разумным решением этих трудностей? По-видимому, он десериализует всю неявную структуру данных каждый раз, когда к ней обращаются, что звучит катастрофично для производительности. Мы могли бы, например, хотим, чтобы наша неявная информация была таблицей или таблицей Cayley, которая занимает концерт ram и должна иметь доступ во время миллионов алгебраических операций.

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

ответ

7

Да, пример из руководства GHC показывает, как добавление сигнатуры типа может изменить семантику кода с неявными параметрами, и я считаю, что это то, что они подразумевают под сломанной вставкой; вложение приложения len_acc1 против приложения len_acc2 дает тот же код, несмотря на то, что два имеют разную семантику.

Что касается обобщения неявных параметров, это означает, что вы не можете написать функцию, которая может работать с несколькими неявными параметрами; нет механизма для абстрагирования над ними, поскольку неявный параметр, используемый функцией, фиксируется его типом. С отражением вы можете легко написать такую ​​функцию, как doSomethingWith :: (Reifies s a, Num a) => Proxy s -> a, которая может работать над любым типом, который подтверждает числовое значение.

Что касается ReifiesStorable, вы смотрите на старую версию пакета отражения; latest version имеет очень эффективную реализацию, в которой reify стоит столько же, сколько вызов функции. Обратите внимание, что даже со старой реализацией вы, как правило, не использовали бы класс ReifiesStorable, а вместо этого - Reifies, который использует ReifiesStorable для восстановления StablePtr, поэтому копируется только несколько байтов, а не весь объект. (Это то, что делает и оригинальная реализация в документе). Обе реализации, безусловно, достаточно быстра для практического использования, при этом старая, «медленная» реализация занимает около 100 мс для подтверждения и отражения 100000 значений, а новая реализация до 10 Миз.

(Полное раскрытие: Я работал над новой реализацией.)

Быстрая реализация зависит от деталей реализации Haskell. Более старая, более медленная реализация автоматически используется для реализации Haskell, с которой быстрая реализация еще не была протестирована; до сих пор, GHC и Hugs, как было показано, работают с быстрой реализацией. Вы можете запросить медленную реализацию с -fslow, но вряд ли она перестанет работать, если GHC значительно не изменит свою реализацию типов. (Даже если это так, вам нужно будет перекомпилировать пакеты, которые используют отражение, чтобы заставить его снова работать.)

+0

Ahh sweet, поэтому 'Data.Reflection' - это все черная магия. :) Есть ли какой-нибудь код или статьи, которые вы рекомендуете читать? «Data.Reflection» уже имеет смысл теперь, когда я замечаю каталог примеров. Однако я должен прочитать другую информацию о Data.Tagged и Data.Proxy. –

 Смежные вопросы

  • Нет связанных вопросов^_^