Что такое AllowAmbiguousTypes и почему это необходимо в этом примере "forall"?
код
{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
-- I know this particular example is silly.
-- But that's not the point here.
g :: forall a . RealFloat a => Bool
g = True
main :: IO ()
main = print (g @Double)
не удается скомпилировать на GHC 8.0 с ошибкой
• Could not deduce (RealFloat a0)
from the context: RealFloat a
bound by the type signature for:
g :: RealFloat a => Bool
at app/Main.hs:3:6-35
The type variable ‘a0’ is ambiguous
• In the ambiguity check for ‘g’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the type signature:
g :: forall a. RealFloat a => Bool
чтобы добавлять AllowAmbiguousTypes
сделает компиляцию кода.
вот мои вопросы:
- что именно
AllowAmbiguousTypes
? - зачем нужно, чтобы этот конкретный код работал?
- боюсь, что добавление
AllowAmbiguousTypes
дает мне больше, чем я действительно хочу в этот конкретный код. Звучит пугающе. Похоже, это сделает Хаскелла тип системы менее безопасен, возможно, в других областях, которые не имеют ничего общего с этим конкретным кодом. Эти опасения беспочвенны? - есть ли альтернативы? В этом случае кажется, что Haskell вставляет
a0
введите переменную, которую я никогда не просил. Нет ли расширения, чтобы сказать Haskell не создавать эти посторонние переменные типа - и использовать только те, которые я явно сказал ему добавить с моим собственным explicitforall a
? - добавил один вопрос из-за user2407038комментарий: Вы бы сказали, что
AllowAmbiguousTypes
является неправильным? Было бы лучше назвать егоAllowUnusedTypeVariables
?
1 ответов
что именно
AllowAmbiguousTypes
?
С последние GHC docs, "типа ty
неоднозначно, если и только если ((undefined :: ty) :: ty)
не typecheck". Расширение AllowAmbiguousTypes
просто отключает эту проверку - это не позволит плохо типизированным программам.
зачем нужно, чтобы этот конкретный код работал?
для того, чтобы проверить это RealFloat a
удовлетворен, когда g
используется, GHC должен знать что?!--7--> есть. У вас нет пути (в vanilla Haskell1) говорить GHC что a
должен быть с a
больше нигде не встречается в типе g
. Никакое количество аннотаций не позволит вам использовать g
без получения неоднозначной ошибки переменной типа.
однако, если вы не использовать g
в любом месте, вы можете получить код для компиляции, поворачивая на AllowAmbiguousTypes
.
боюсь, что добавление
AllowAmbiguousTypes
это дает мне больше чем я действительно хочу в этом конкретном коде. Звучит пугающе. Похоже, это сделает систему типов Haskell менее безопасной, возможно, в других областях, которые не имеют ничего общего с этим конкретным кодом. Эти опасения беспочвенны?
Да, они: проверка неоднозначности позволяет вам поймать определения, которые не могут (в vanilla Haskell, у которого нет TypeApplications
1) используется без возникновения неоднозначной ошибки переменной типа. Отключение этой проверки означает, что вы будет отображаться неоднозначное сообщение переменной типа при использовании выражения (или функции) вместо его сайта определения.
есть ли альтернативы? В этом случае кажется, что Haskell вставляет
a0
введите переменную, которую я никогда не просил. Нет ли расширения, чтобы сказать Haskell не создавать эти посторонние переменные типа - и использовать только те, которые я явно сказал ему добавить с моим собственным explicitforall a
?
на a0
is исходя из проверки двусмысленности, которую я упомянул в начале этого ответа. GHC просто использует имя a0
чтобы было ясно, что он отличается от a
. Проверка неоднозначности в основном просто пытается typecheck
((undefined :: forall a. RealFloat a => Bool) :: forall a0. RealFloat a0 => Bool)
AllowAmbiguousTypes
удаляет эту проверку. Я не думаю, что есть расширение, которое отключает проверки двусмысленности только на сигнатурах типа с явным forall
s (хотя это может быть аккуратно и полезно!).
вы бы сказали, что
AllowAmbiguousTypes
это неправильно? Было бы лучше назвать егоAllowUnusedTypeVariables
?
называть вещи трудно. :)
текущее имя ссылается на тип ошибок, которые вы получаете без включенного расширения, поэтому это не плохое имя. Думаю, это вопрос мнения. (Многие люди также хотят Monad
называлась что-то вроде FlatMapAble
.)
1 до TypeApplications
(что является относительно новым расширением от GHC 8.0), действительно не было никакого способа использование выражений, которые вызвали проверку неоднозначности без получения ошибки переменной неоднозначного типа, поэтому AllowAmbiguousTypes
было намного менее полезно.