Как я специализируюсь с явным типом приложения?

С 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, но, похоже, стыдно не использовать новый блестящий способ.

Ответы

Ответ 1

Это не поддерживается в GHC 8.0, но теперь является предметом proposal, чтобы поддержать его в будущих GHC.