Ответ 1
Это не поддерживается в GHC 8.0, но теперь является предметом proposal, чтобы поддержать его в будущих GHC.
С GHC 8.0 я могу написать неоднозначную функцию, которая перегружена над некоторым типом, не упомянутым в основной части его сигнатуры типа, а затем вызывается с использованием явного приложения типа:
{-# LANGUAGE ScopedTypeVariables, RankNTypes,
AllowAmbiguousTypes, TypeApplications, TypeFamilies #-}
showRead :: forall t . (Read t, Show t) => String -> String
showRead x = show (read x :: t)
showReadInt = showRead @Int
Я хотел бы использовать SPECIALIZE
прагму, чтобы заставить специализацию showRead
для Int
(у моего реального кода есть фактический сайт вызова в другой модуль). Однако обычный синтаксис SPECIALIZE
основан на написании основной части сигнатуры типа, например:
{-# SPECIALIZE showRead :: String -> String #-}
и в этом случае это не позволяет мне указать, что должно быть t
, и предсказуемо дает ошибку в том, что он является двусмысленным.
Я попытался использовать ограничение равенства:
{-# SPECIALISE showRead :: forall t . (Read t, Show t, t ~ Int) => String -> String #-}
но это просто дало ошибку:
• Could not deduce (Read t0) a SPECIALISE pragma for ‘showRead’ from the context: (Read t, Show t, t ~ Int) bound by the type signature for: showRead :: (Read t, Show t, t ~ Int) => String -> String at foo.hs:4:1-76 The type variable ‘t0’ is ambiguous
Есть ли способ сделать это? Конечно, я мог бы просто использовать Proxy
, но, похоже, стыдно не использовать новый блестящий способ.
Это не поддерживается в GHC 8.0, но теперь является предметом proposal, чтобы поддержать его в будущих GHC.