我最近发现-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
的类型。有没有办法让我的包装工作?