我怎样才能弄清楚p0是什么?

时间:2013-03-25 11:59:18

标签: haskell

我正在尝试理解引用类型变量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.

1 个答案:

答案 0 :(得分:6)

这是一个猜测,但这里有:

p0已在p类型签名中的bar重命名。

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

此处p仅发生在=>的左侧。只能从呼叫网站推断出kv。可以有许多类型p在给予Metric时给出相同的结果,并且编译器无法假设p中的bar是相同的作为p中的wombat,即使Metric p在两种情况下都相同。

在这种情况下,我会将类型签名更改为

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

因为bar不使用任何其他约束。

如果您的真实代码bar 确实使用其他约束,我会add a proxy argument(如果我的值为p,则可以wombat适当的类型,a -> pp -> a或{{1}}等,以帮助类型检查。