Недавно я обнаружил -XTypeApplications
, что позволяет мне писать сокращенный код. Рассмотрим следующее:
{-# LANGUAGE AllowAmbiguousTypes, DataKinds, KindSignatures, RankNTypes,
ScopedTypeVariables, TypeApplications #-}
import Data.Tagged
import Data.Proxy
class Foo (a :: Bool) where
foo :: Tagged a Int
instance Foo 'True where
foo = 3
instance Foo 'False where
foo = 4
вместо записи proxy foo (Proxy::Proxy 'True)
теперь я могу написать untag $ foo @'True
, что сэкономит мне много шаблона Proxy
. Это хорошо, но мы можем сделать лучше с двусмысленными типами:
foo' :: forall (a :: Bool) . (Foo a) => Int
foo' = untag $ foo @a
Теперь я могу написать foo' @'True
! Обратите внимание, что хотя тип был неоднозначным до -XTypeApplications
, это уже не так, поскольку я могу указать тип a
. Я думаю, что это очень здорово, но другие могут и не быть. Поэтому я надеялся представить обертку
wrapAmbiguous :: forall (a :: Bool) b . (Foo a) => (forall (t :: Bool) . (Foo t) => b) -> Tagged a b
wrapAmbiguous f = Tagged $ f @a
(еще более общий в моем фактическом использовании, но это имеет смысл), так что пользователям не нужно -XTypeApplications
. Однако, когда я пытаюсь использовать wrapAmbiguous
как proxy (wrapAmbiguous foo') (Proxy::Proxy 'True)
, я получаю ошибку
• Could not deduce (Foo a0) arising from a use of ‘foo'’
from the context: Foo t
bound by a type expected by the context:
Foo t => Int
at Foo.hs:26:18-35
The type variable ‘a0’ is ambiguous
These potential instances exist:
instance Foo 'False -- Defined at Foo.hs:12:10
instance Foo 'True -- Defined at Foo.hs:9:10
• In the first argument of ‘wrapAmbiguous’, namely ‘foo'’
In the first argument of ‘proxy’, namely ‘(wrapAmbiguous foo')’
In the second argument of ‘($)’, namely
‘proxy (wrapAmbiguous foo') (Proxy :: Proxy True)’
Мне кажется, что это должно быть законным, но GHC, по-видимому, не может объединить тип foo'
с forall (t :: Bool) (Foo t) => b
. Есть ли способ заставить мою обертку работать?