I'm implementing a notion of inner product that's general over the container and numerical types. The definition states that the return type of this operation is a (non-negative) real number.
One option (shown below) is to write all instances by hand, for each numerical type (Float, Double, Complex Float, Complex Double, Complex CFloat, Complex CDouble, etc.). The primitive types aren't many, but I dislike the repetition.
Another option, or so I thought, is to have a parametric instance with a constraint such as RealFloat
(which represents Float
and Double
).
{-# language MultiParamTypeClasses, TypeFamilies, FlexibleInstances #-}
module Test where
import Data.Complex
class Hilbert c e where
type HT e :: *
dot :: c e -> c e -> HT e
instance Hilbert [] Double where
type HT Double = Double
dot x y = sum $ zipWith (*) x y
instance Hilbert [] (Complex Double) where
type HT (Complex Double) = Double
a `dot` b = realPart $ sum $ zipWith (*) (conjugate <$> a) b
Question
Why does the instance below not work ("Couldn't match type e
with Double
.. expected type HT e
, actual type e
")?
instance RealFloat e => Hilbert [] e where
type HT e = Double
dot x y = sum $ zipWith (*) x y
sum
returns ane
(sincex
andy
have type[e]
) butdot
should be returning aHT e = Double
. Somehow, you'll need to converte
to aDouble
. – Alec