2016-09-30 44 views
0

我想使用一個typeclass將字典傳遞到一個函數,其中該字典的值由函數的兩個類型參數的類型唯一指定。我該如何改變這種說法,體型應該等於參數類型?

當我編譯此代碼時,我在評論中收到錯誤消息。

如何修改此代碼以避免此歧義?我希望身體中的a和b類型與形式參數中的a和b類型相同。

{-# LANGUAGE MultiParamTypeClasses#-} 

class C a b where 
    a :: a 
    b :: b 

f :: C a b => a -> b 
f a = b 


-- $ runhaskell toy2.hs 
-- toy2.hs:8:7: 
--  Could not deduce (C a0 b) arising from a use of ‘b’ 
--  from the context (C a b) 
--  bound by the type signature for f :: C a b => a -> b 
--  at toy2.hs:7:6-20 
--  The type variable ‘a0’ is ambiguous 
--  Relevant bindings include f :: a -> b (bound at toy2.hs:8:1) 
--  In the expression: b 
--  In an equation for ‘f’: f a = b 

然後使用會像

instance C String Double where 
    a = "foo" 
    b = 42.0 

f "bar" = 42.0 
+0

他們已經是你想要的類型。麻煩的是,沒有辦法使用'b',因爲它的類型沒有提及'a'。 – melpomene

+0

理想情況下,如果使用了足夠的擴展名,比如'AllowAmbiguousTypes,TypeArguments,ScopedTypeVariables','b @ a @ b'可以工作。不過,我現在無法測試。 – chi

+0

你能澄清你想完成什麼嗎?假設你有'instance C String Double where a =「foo」; b = 42.0'。你期望'f'bar''產生什麼? – user2297560

回答

2

使用顯式類型參數。我不相信這是一個好方法, 雖然。

{-# LANGUAGE AllowAmbiguousTypes, TypeApplications, 
      ScopedTypeVariables, MultiParamTypeClasses #-} 

class C a b where 
    getA :: a 
    getB :: b 

foo :: forall a b. C a b => a -> b 
foo _ = getB @ a 

instance C Int Char where 
    getA = 3 
    getB = 'a' 

test :: Char 
test = foo @ Int @ Char 23 

你確定你沒有ab之間的函數關係做?否則,你必須始終用明確的類型參數消除歧義。

+0

這似乎很適合我的問題。我想我可以將類型應用程序劃分爲代碼的一小部分。謝謝! – ryantm

3

爲了說明這個問題,考慮這兩個實例:

instance Char Double where 
    a = 'x' 
    b = 42.0 

instance Char Int where 
    a = 'x' 
    b = 17 

現在f 'c'需要平等b,但b?有兩個C可以工作的實例。

一種解決方案是使用一個函數依賴於強制執行的b類型取決於a類型:

class C a b | b -> a where 
    a :: a 
    b :: b 

只是注意,你可能會碰到需要明確的標註了一些類型推斷的問題。

相關問題