2013-03-25 45 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

相关问题