我有一個類型的類GHC:爲什麼輸入歧義走開使用讓
class (Monad f) => Test f where
test ::() -> f()
和實例
instance Test (ErrorT String (Identity)) where
test pat = return pat
如果我運行一個單子棧參照本實例時,GHC可以」找不到什麼單子我說的(在Either String
單子的do
塊):
rhs' <- runIdentity $ runErrorT $ test rhs
產生的錯誤信息:
Ambiguous type variable `f0' in the constraint:
(Test f0) arising from a use of `test'
...
但是,如果我的部分test rhs
綁定到一個變量:
let action = test rhs
rhs' <- runIdentity $ runErrorT $ action
它的工作原理,即使變量不能用於其他地方所以沒有什麼新的可以推斷一下。
這是怎麼可能的,如果我沒有添加類型檢查器使用的信息?爲什麼不能找出相應的第一個公式的類型?或者這兩個公式不相等? Haskell類型檢查器的哪個部分(或者desugaring規則?)在這裏我不理解?
我使用的擴展MultiParamTypeClasses
,FlexibleInstances
和ScopedTypeVariables
編輯:我簡單的例子,從而出現奇怪的問題,而不需要我的代碼的其餘部分(以及更短的單子棧),但現在它看起來荒謬。該語句的完整的上下文是:
doStuff :: (Map Int()) -> Either String (Map Int())
doStuff g = run (snd . head . Map.toList $ g) g where
run ::() -> Map Int() -> Either String (Map Int())
run rhs g = do
let action = test rhs
rhs' <- runIdentity $ runErrorT $ test rhs -- or: action
return g
你能把這個減少到一個小的可重複的例子嗎?這個代碼中有太多的外部事物可以自己嘗試 - 例如'Pattern','Symbol','g'和'rhs'。 – 2014-10-04 17:43:34
我認爲在你的cutdown代碼中,如果你不使用'action',那麼'let action = test rhs'就會產生歧義。如果我使用'test rhs'並且刪除'let action ='行,它編譯得很好。 – 2014-10-04 18:34:17
另外,假設這不是你原來的代碼的問題,如果你不使用'$',即寫'runIdentity(runErrorT(test rhs))'',會發生什麼?這只是一個猜測,但在某些時候,有一些有趣的規則可以幫助'運行'...'類型檢查,這只是可能的。 – 2014-10-04 18:39:10