Tob*_*eck 6 haskell typeclass data-kinds
以下示例是我现实生活中的问题的简化版本.它似乎在某种程度上类似于从DataKinds约束的存在类型中检索信息,但我无法得到我正在寻求的答案.
假设我们有一个有限的,提升的DataKind K类型A和B,以及poly-kinded Proxy数据类型来生成类型*的类型.
{-# LANGUAGE DataKinds, PolyKinds, GADTs, FlexibleInstances, FlexibleContexts #-}
data K = A | B
data Proxy :: k -> * where Proxy :: Proxy k
Run Code Online (Sandbox Code Playgroud)
现在我想写Show-instances每一个类型Proxy a,其中a是怎么样的K,这是完全二:
instance Show (Proxy A) where show Proxy = "A"
instance Show (Proxy B) where show Proxy = "B"
Run Code Online (Sandbox Code Playgroud)
但是要使用Show-instance,我必须明确提供上下文,即使类型仅限于K:
test :: Show (Proxy a) => Proxy (a :: K) -> String
test p = show p
Run Code Online (Sandbox Code Playgroud)
我的目标是摆脱类型类约束.这似乎并不重要,但在我的实际应用中,这具有重大意义.
我也可以定义一个单一但更通用的Show例子:
instance Show (Proxy (a :: K)) where show p = "?"
Run Code Online (Sandbox Code Playgroud)
这实际上允许我放弃约束,但新问题是区分两种类型A和B.
那么,有没有办法吃我的蛋糕呢?也就是说,不必在类型test(类型注释很好)中提供类型类约束,并且仍然具有两种不同的show实现(例如通过以某种方式区分类型)?
其实,这也将是好放弃整个类型的类,如果我可以简单地各自的类型(关联A,B)与他们的具体数值,(在这里"A","B"在一个方面,我只是有类型的信息).不过,我不知道该怎么做.
我非常感谢任何提供的见解.
不,这是不可能的.在您只有"类型信息"的上下文中,在运行时,您确实没有任何信息.类型信息被删除.所以即使是封闭的类型,原则上可以显示给定的类型,你总是可以提出一个字典,你仍然需要类约束.类约束确保在编译时,当GHC知道类型时,它可以选择要传递的适当实例.在运行时,输入它的信息会丢失,并且没有机会这样做.编写"一刀切"的实例确实有效,因为确切的类型对于选择不再重要.
我不知道全貌,但有可能通过明确地将类字典或字符串本身与您传递的值捆绑在一起来解决这个问题...
您可以添加另一个类.
class Kish (k :: K) where
toK :: proxy k -> K
instance Kish A where
toK _ = A
instance Kish B where
toK _ = B
instance Kish k => Show (Proxy k) where
showsPrec n _ = case toK (Proxy :: Proxy k) of
A -> ...
B -> ...
Run Code Online (Sandbox Code Playgroud)
现在你仍然会遇到一个上下文,但它是一个更普遍的上下文,也可能对其他事情有用.
如果事实证明您需要经常区分代理,那么您应该切换到GADT,您可以根据需要检查而不是使用代理.