I struggled for hours to get something like the following right:
to_xyz_regular :: (RealFrac t) => (RegularSpd t) -> (t, t, t)
to_xyz_regular spd@(RegularSpd lambda_min lambda_max spectrum delta inverse_delta) =
let
l = length cie_x - 1
il = 1.0 / fromIntegral l
samp i = sample spd $ lambda_min + inverse_delta * fromIntegral i
integrate curve = (foldr (+) 0 $
map (\i -> curve!!i * samp i) [0..l]) * il
in (integrate cie_x, integrate cie_y, integrate cie_z)
(this is a conversion routine from color SPDs / spectra to XYZ colors).
The values cie_XXX
were defined as follows:
cie_start = 360.0
cie_end = 830.0
cie_x = [0.0001299000, 0.0001458470, 0.0001638021, 0.0001840037,
....]
cie_y = ....
cie_z = ....
but then giving me roughly
Could not deduce (t ~ Double)
from the context (RealFrac t)
....
the problem being that the cie_XXX
values where stored as Double
, where I really would have liked them being poylmorphic.
The solution I finally found was to add type signatures for those values:
cie_start :: (RealFrac t) => t
cie_end :: (RealFrac t) => t
cie_x :: (RealFrac t) => [t]
cie_y :: (RealFrac t) => [t]
cie_z :: (RealFrac t) => [t]
Now my question is: Is this the proper way to have polymorphic values/literals in Haskell?
It was a bit tough for me to find a solution on websearch, because books, tutorials etc. mention type signatures only for parametric functions -> Are values just parameterless functions?