関数の戻り値の型にのみ現れる型変数を理解して使用する方法を理解するのに苦労しています。
diagrams-cairoを使用して、2 つの図をピクセルごとに比較しようとしています。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
ですか?
このコードの書き方に根本的な何かが欠けているように感じます。どんな助けでも大歓迎です。