可见类型应用程序是否是“代理”参数的安全替代方案?
Are visible type applications a safe alternative to `Proxy` arguments?
鉴于可见类型应用程序现在可以为值或函数填充模糊类型,这现在可以完全替代 Proxy 的使用吗?
我看到的一个缺点是可能必须启用 AllowAmbiguousTypes
,但由于不允许使用不明确的类型来捕获错误留下不明确的类型签名,因此此安全网将不再存在。还有其他需要考虑的问题吗?
在现代代码中,我尽量避免Proxy
,更喜欢模棱两可的类型和类型应用。我看不出这样做有什么坏处。
不过,如果我没记错的话,在某些极端情况下我们仍然需要像 Proxy
这样的东西。例如:
class C a where name :: String
instance C Int where name = "Int"
instance C Bool where name = "Bool"
data T where
T :: forall a . C a => !(Proxy a) -> T
t1 :: T
t1 = T @Int Proxy
t2 :: T
t2 = T @Bool Proxy
nameFromT :: T -> String
nameFromT (T (Proxy :: Proxy a)) = name @a
没有Proxy
,我不知道如何将类型绑定到最后一行的a
:
data T where
T :: forall a . C a => T
t1 :: T
t1 = T @Int
t2 :: T
t2 = T @Bool
nameFromT :: T -> String
nameFromT (T @a) = name @a
-- Error:
-- Type applications in patterns are not yet supported
在这种特定情况下,我能做的最好的事情就是求助于 Dict
。
data T where
T :: forall a . Dict (C a) -> T
仍然,它仍然是 Proxy
-like T
现在有一个不应该存在的可见(非类型级)参数。
鉴于可见类型应用程序现在可以为值或函数填充模糊类型,这现在可以完全替代 Proxy 的使用吗?
我看到的一个缺点是可能必须启用 AllowAmbiguousTypes
,但由于不允许使用不明确的类型来捕获错误留下不明确的类型签名,因此此安全网将不再存在。还有其他需要考虑的问题吗?
在现代代码中,我尽量避免Proxy
,更喜欢模棱两可的类型和类型应用。我看不出这样做有什么坏处。
不过,如果我没记错的话,在某些极端情况下我们仍然需要像 Proxy
这样的东西。例如:
class C a where name :: String
instance C Int where name = "Int"
instance C Bool where name = "Bool"
data T where
T :: forall a . C a => !(Proxy a) -> T
t1 :: T
t1 = T @Int Proxy
t2 :: T
t2 = T @Bool Proxy
nameFromT :: T -> String
nameFromT (T (Proxy :: Proxy a)) = name @a
没有Proxy
,我不知道如何将类型绑定到最后一行的a
:
data T where
T :: forall a . C a => T
t1 :: T
t1 = T @Int
t2 :: T
t2 = T @Bool
nameFromT :: T -> String
nameFromT (T @a) = name @a
-- Error:
-- Type applications in patterns are not yet supported
在这种特定情况下,我能做的最好的事情就是求助于 Dict
。
data T where
T :: forall a . Dict (C a) -> T
仍然,它仍然是 Proxy
-like T
现在有一个不应该存在的可见(非类型级)参数。