2017-04-07 78 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