2013-03-25 47 views
4

我想了解一個編譯器錯誤消息,它指的是一個類型變量p0。在大多數情況下,錯誤消息會告訴我編譯器調用的是什麼,p0,沿着「p0是一個由......綁定的剛性類型變量」的行,但在這種情況下不行。通常,如果編譯器錯誤消息引用了它已經分配的類型變量(而不是類型變量,我在類型簽名中引用),並且它不告訴我類型變量綁定的位置,如何我可以弄明白嗎?我怎樣才能知道p0是什麼?

{-# LANGUAGE TypeFamilies, FlexibleContexts, MultiParamTypeClasses #-} 
import Data.List (minimumBy) 
import Data.Ord (comparing) 
import qualified Math.Geometry.Grid as G (Grid(..)) 
import qualified Math.Geometry.GridMap as GM (GridMap(..)) 
import Prelude hiding (lookup) 

class Pattern p where 
    type Metric p 
    difference ∷ p → p → Metric p 
    makeSimilar ∷ p → Metric p → p → p 

data SOM gm k p = SOM 
    { 
    sGridMap :: gm p, 
    sLearningFunction :: Int -> Int -> Metric p, 
    sCounter :: Int 
    } 

foo 
    :: (Pattern p, Ord v, v ~ Metric p, GM.GridMap gm p, GM.GridMap gm v, 
     k ~ G.Index (GM.BaseGrid gm p), k ~ G.Index (GM.BaseGrid gm v)) => 
    SOM gm k p -> p -> [(k, v)] 
foo s p = GM.toList . GM.map (p `difference`) . sGridMap $ s 

bar :: (Pattern p, Ord v, v ~ Metric p) => [(k, v)] -> k 
bar ds = fst . minimumBy (comparing snd) $ ds 

wombat 
    :: (Pattern p, Ord v, v ~ Metric p, GM.GridMap gm p, GM.GridMap gm v, 
     k ~ G.Index (GM.BaseGrid gm p), k ~ G.Index (GM.BaseGrid gm v)) => 
    SOM gm k p -> p -> (k, [(k, v)]) 
wombat s p = (bar diffs, diffs) 
    where diffs = foo s p 

這裏的錯誤:

λ> :l ../amy.hs 
[1 of 1] Compiling Main    (../amy.hs, interpreted) 

../amy.hs:33:19: 
    Could not deduce (v ~ Metric p0) 
    from the context (Pattern p, 
         Ord v, 
         v ~ Metric p, 
         GM.GridMap gm p, 
         GM.GridMap gm v, 
         k ~ G.Index (GM.BaseGrid gm p), 
         k ~ G.Index (GM.BaseGrid gm v)) 
     bound by the type signature for 
       wombat :: (Pattern p, Ord v, v ~ Metric p, GM.GridMap gm p, 
          GM.GridMap gm v, k ~ G.Index (GM.BaseGrid gm p), 
          k ~ G.Index (GM.BaseGrid gm v)) => 
          SOM gm k p -> p -> (k, [(k, v)]) 
     at ../amy.hs:(30,10)-(32,40) 
     `v' is a rigid type variable bound by 
      the type signature for 
      wombat :: (Pattern p, Ord v, v ~ Metric p, GM.GridMap gm p, 
         GM.GridMap gm v, k ~ G.Index (GM.BaseGrid gm p), 
         k ~ G.Index (GM.BaseGrid gm v)) => 
         SOM gm k p -> p -> (k, [(k, v)]) 
      at ../amy.hs:30:10 
    In the expression: bar diffs 
    In the expression: (bar diffs, diffs) 
    In an equation for `wombat': 
     wombat s p 
      = (bar diffs, diffs) 
      where 
       diffs = foo s p 
Failed, modules loaded: none. 

回答

6

這是一個有點猜測,但在這裏有雲:

p0pbar的類型簽名改名。

bar :: (Pattern p, Ord v, v ~ Metric p) => [(k, v)] -> k 

這裏p只發生在=>的左側。可以從呼叫站點推斷出只有kvp可能有多種給出相同的結果,並且編譯器不能假定pbar是在wombat相同,即使Metric p在兩種情況下都是相同的。

在這種情況下,我會類型簽名更改爲

bar :: Ord v => [(k, v)] -> k 

bar不使用任何的其他限制。

如果在您的實際代碼bar使用其他約束,我會add a proxy argument(這可能是p型的,如果我有合適的類型躺在附近的一個值,如wombat做,或a -> pp -> a,等)來幫助類型檢查。

+0

我認爲從'wombat'向'bar'傳遞'p'也能做到這一點,但由於代碼不是獨立的,因此很難說。 – yatima2975 2013-03-25 12:38:24

+0

@ yatima2975我認爲你是對的。我不知何故忽略了'wombat'直接帶了'p'。 – dave4420 2013-03-25 12:46:05

相關問題