我正在尝试理解引用类型变量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.
答案 0 :(得分:6)
这是一个猜测,但这里有:
p0
已在p
类型签名中的bar
重命名。
bar :: (Pattern p, Ord v, v ~ Metric p) => [(k, v)] -> k
此处p
仅发生在=>
的左侧。只能从呼叫网站推断出k
和v
。可以有许多类型p
在给予Metric
时给出相同的结果,并且编译器无法假设p
中的bar
是相同的作为p
中的wombat
,即使Metric p
在两种情况下都相同。
在这种情况下,我会将类型签名更改为
bar :: Ord v => [(k, v)] -> k
因为bar
不使用任何其他约束。
如果您的真实代码bar
确实使用其他约束,我会add a proxy argument(如果我的值为p
,则可以wombat
适当的类型,a -> p
,p -> a
或{{1}}等,以帮助类型检查。