具有约束 return 类型的类型类实例

Typeclass instances with constrained return type

我正在实现一个内积的概念,它在容器和数字类型上是通用的。定义指出此操作的 return 类型是(非负)实数。 一种选择(如下所示)是为每种数值类型(Float、Double、Complex Float、Complex Double、Complex CFloat、Complex CDouble 等)手动编写所有实例。原始类型不多,但我不喜欢重复。 另一种选择,或者我认为,是有一个带有约束的参数实例,例如 RealFloat(代表 FloatDouble)。

{-# 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

问题

为什么下面的实例不起作用 ("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 只产生一个 e,但你希望结果是 Double。由于 e 限制为 RealFrac,这很容易解决,因为任何 Real(尽管在数学上有问题)都可以转换为一个 Fractional:

  dot x y = realToFrac . sum $ zipWith (*) x y

但是,该通用实例会阻止您同时定义复杂实例:使用 instance RealFloat e => Hilbert [] e where 可以涵盖 所有 类型,即使它们不是真正的实数。您仍然可以将 Complex 实例化为重叠实例,但如果可以的话,我宁愿远离它们。

是否应该在 * -> * 上定义这样的向量空间 类 也值得怀疑。是的,linear also does it this way, but IMO parametricity doesn't work in our favour in this application. Have you checked out the vector-space package? Mind, it isn't exactly complete for doing serious linear algebra; that's a gap I hope to fill with my linearmap-category package.