Насколько опасно расширение AllowAmbiguousTypes при использовании с расширением TypeApplications?
В руководстве GHC приводится следующий пример неоднозначного типа:
class C a
f :: C a => Int
f = 3
Это не может быть скомпилировано, если AllowAmbiguousTypes не используется со следующим сообщением:
file.hs:8:6: error:
• Could not deduce (C a0)
from the context: C a
bound by the type signature for:
f :: forall a. C a => Int
at file.hs:8:6-15
The type variable ‘a0’ is ambiguous
• In the ambiguity check for ‘f’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the type signature: f :: C a => Int
|
8 | f :: C a => Int
| ^^^^^^^^^^
С AllowAmbiguousTypes компилируется правильно.
Однако следующий пример не может быть скомпилирован даже с AllowAmbiguousTypes:
class C a
f :: C a => Int
f = 3
g :: C a => Int
g = f
При попытке его компиляции выдает следующую ошибку:
file.hs:12:5: error:
• Could not deduce (C a0) arising from a use of ‘f’
from the context: C a
bound by the type signature for:
g :: forall a. C a => Int
at file.hs:11:1-15
The type variable ‘a0’ is ambiguous
• In the expression: f
In an equation for ‘g’: g = f
|
12 | g = f
| ^
Это можно записать, включив TypeApplications и записав его следующим образом:
class C a
f :: C a => Int
f = 3
g :: forall a. C a => Int
g = f @a
AllowAmbiguousTypes звучит пугающе, но, судя по описанию в руководстве GHC, он кажется довольно безобидным, особенно при использовании с TypeApplications.
Не похоже, что AllowAmbiguousTypes вызовет ошибки во время выполнения, верно?
Эта комбинация AllowAmbiguousTypes и TypeApplications также, кажется, используется в некоторых довольно популярных пакетах, таких как ограничения.
Этот вопрос основан на ответе, который я получил на другой вопрос, в котором для хорошего эффекта использовались как AllowAmbiguousTypes, так и TypeApplications: stackoverflow.com/a/49671162/3040129.
Я не буду возражать, если они оба будут включены по умолчанию - на самом деле, мне бы это очень хотелось. Без них нам нужны дополнительные аргументы proxy a, которые мне кажутся хакерскими: почему я должен передавать значение времени выполнения, которое не несет никакой информации, только для того, чтобы сообщить компилятору, что я хочу использовать тип a? Это должно быть аргументом времени компиляции, и теперь это возможно, если мы будем использовать foo @ a. Неоднозначные типы очень хороши, если у вас есть приложения типа. Теперь у них нет обратной стороны.





Алексис Кинг отметила это в своем комментарии; он заслуживает того, чтобы его возвысили до уровня ответа.
AllowAmbiguousTypesis completely safe, in the sense that it is perfectly sound, will not make the compiler diverge, and cannot lead to runtime errors. It was just mostly useless prior to the introduction ofTypeApplications. The combination of the two is a perfectly reasonable thing.
AllowAmbiguousTypesполностью «безопасен» в том смысле, что он абсолютно надежен, не приведет к отклонениям компилятора и не может привести к ошибкам выполнения, он был просто бесполезен до появленияTypeApplications. Комбинация того и другого - вполне разумная вещь.