4

我试图理解引用类型变量的编译器错误消息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.
4

1 回答 1

6

这有点猜测,但这里有:

p0pinbar的类型签名重命名。

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

这里p只出现在=>. 只有kv可以从调用站点中推断出来。可能有许多类型p在给定时给出相同的结果Metric,并且编译器不能假设pin与inbar相同,即使在两种情况下都是相同的。pwombatMetric p

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

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

asbar不使用任何其他约束。

如果在您的真实代码bar 中确实使用了其他约束,我会添加一个代理参数p(如果我有一个适当类型的值,那么它可能是类型,就像wombat这样,or of a -> porp -> a等​​)来帮助类型检查器。

于 2013-03-25T12:32:42.563 回答