我在理解如何理解和使用只出现在函数返回类型中的类型变量时遇到了一些麻烦。
我正在尝试使用diagrams-cairo逐个像素地比较两个图表。renderToList函数具有以下类型:
renderToList :: (Ord a, Floating a) => Int -> Int -> Diagram Cairo R2 -> IO [[AlphaColour a]]
返回列表的列表AlphaColour a
。请记住a
,我想我可以对这些值(Ord a, Floating a)
使用数学和比较运算:AlphaColour a
import Diagrams.Prelude
import Diagrams.Backend.Cairo
import Diagrams.Backend.Cairo.List
import Data.Colour
import Data.Colour.SRGB
import Data.Foldable (fold)
import Data.Monoid
cmp :: Diagram Cairo R2 -> Diagram Cairo R2 -> Diagram Cairo R2 -> IO Bool
cmp base img1 img2 = do
baseAlphaColours <- renderToList 400 400 base
img1AlphaColours <- renderToList 400 400 img1
img2AlphaColours <- renderToList 400 400 img2
return $ (imgDiff baseAlphaColours img1AlphaColours) < (imgDiff baseAlphaColours img2AlphaColours)
imgDiff :: (Ord a, Monoid a, Floating a) => [[AlphaColour a]] -> [[AlphaColour a]] -> a
imgDiff img1 img2 = fold $ zipWith diffPix (concat img1) (concat img2)
diffPix :: (Ord a, Floating a) => AlphaColour a -> AlphaColour a -> a
diffPix a1 a2 = (diffRed * diffRed) - (diffGreen * diffGreen) - (diffBlue * diffBlue)
where red a = channelRed $ toSRGB (a `over` black)
green a = channelGreen $ toSRGB (a `over` black)
blue a = channelBlue $ toSRGB (a `over` black)
diffRed = (red a1) - (red a2)
diffGreen = (green a1) - (green a2)
diffBlue = (blue a1) - (blue a2)
但是我得到了不祥的编译错误
Ambiguous type variable `a0' in the constraints:
(Floating a0)
arising from a use of `renderToList' at newcompare.hs:11:37-48
(Ord a0)
arising from a use of `renderToList' at newcompare.hs:11:37-48
(Monoid a0)
arising from a use of `imgDiff' at newcompare.hs:14:27-33
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of a 'do' block:
baseAlphaColours <- renderToList 400 400 base
In the expression:
do { baseAlphaColours <- renderToList 400 400 base;
img1AlphaColours <- renderToList 400 400 img1;
img2AlphaColours <- renderToList 400 400 img2;
return
$ (imgDiff baseAlphaColours img1AlphaColours)
< (imgDiff baseAlphaColours img2AlphaColours) }
In an equation for `cmp':
cmp base img1 img2
= do { baseAlphaColours <- renderToList 400 400 base;
img1AlphaColours <- renderToList 400 400 img1;
img2AlphaColours <- renderToList 400 400 img2;
.... }
我理解为编译器想知道renderToList
调用的完整类型。
但我不明白的是:
- 为什么编译器需要知道完整类型?我想我只使用可用于
Ord
和Floating
实例的操作。 - 如果我确实需要提供一种类型,那么我将在代码中的确切位置定义这种类型。
- 我怎么知道返回的完整具体类型
renderToList
是什么?
我觉得我在编写这段代码的方式上遗漏了一些基本的东西,任何帮助都将不胜感激。