2017-04-07 75 views
0

我想使用参数化类型类。下面是我的源代码:Haskell类型类别中的模糊类型

class (CContext3D c k v) => CBuilder3D c a k v where 
    build3D :: c -> a -> String -> HSL HLangJS HLangJS 

在编译时我收到以下错误:

Could not deduce (CBuilder3D c a k0 v0) 
from the context: CBuilder3D c a k v 
bound by the type signature for: 
    build3D :: CBuilder3D c a k v => 
           c -> a -> String -> HSL HLangJS HLangJS 

下面的代码工作正常:

class (CContext3D c KeyContext3D String) => CBuilder3D c a where 
    build3D :: c -> a -> String -> HSL HLangJS HLangJS 

这怎么可能释放类的实例取决于k和v类型?

回答

2

假设有一个电话给您的build3D。从该调用的上下文中,编译器必须找到适当的实例。这涉及到找到变量c a k v的值。但是,build3D的类型没有提及k v,所以不可能找到那些。

更具体地讲,如果我们有

instance CBuilder3D c a K1 V1 where ... 
instance CBuilder3D c a K2 V2 where ... 

及其相关build3D功能将具有完全相同的类型,编译器没有办法选择其中的一个。

可能的解决方案:

如果可能的话,你应该使用函数依赖或类型的家庭指出的kv值是由其它参数来确定。这可能是或不是,取决于你的具体课程。

否则,您可以尝试启用AllowAmbiguousTypesTypeApplications,并保持模糊类型。但是,在每次调用中,您现在必须明确指定这些类型,如build3D @t1 @t2 @t3 @t4 x1 x2 x3,其中t1,...是所有变量c a k v的类型。不是非常方便。

另一种选择是让k,v出现在同一个代理类型:

import Data.Proxy 

class (CContext3D c k v) => CBuilder3D c a k v where 
    build3D :: proxy k -> proxy v -> c -> a -> String -> HSL HLangJS HLangJS 

现在每次调用应该像build3D (Proxy :: Proxy K1) (Proxy :: Proxy V1) x1 x2 x3