我一直在尝试通过编写 Vector 库来找出 Haskell 类型系统的更多细节。理想情况下,我想要一个工作起来有点像 C++ 的重载向量乘法运算,即您可以按任意顺序将任意大小的向量乘以一个标量。我尝试结合多个参数类型类和类型族扩展来做到这一点:
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}
data Vec2 a = Vec2 (a,a) deriving (Show, Eq, Read)
class Vector a where
(<+>) :: a -> a -> a
class VectorMul a b where
type Result a b
(<*>) :: a -> b -> Result a b
instance (Num a) => Vector (Vec2 a) where
Vec2 (x1,y1) <+> Vec2 (x2,y2) = Vec2 (x1+x2, y1+y2)
instance (Num a) => VectorMul (Vec2 a) a where
type Result (Vec2 a) a = (Vec2 a)
Vec2 (x,y) <*> a = Vec2 (x*a, y*a)
works :: (Num a) => Vec2 a -> a -> Vec2 a
works a b = a <*> b
这段代码似乎可以工作,至少在函数中使用时是这样works
。但是当我尝试在Vec2 (3,4) <*> 5
GHCi 中输入一个简单的表达式时,它会报告(Num xx)
类型变量不明确。这对我来说很奇怪......在这种情况下我错过了什么?Haskell 应该能够为文字选择相同的任意类型,以使类型表达式起作用(就像它在works
函数中所做的那样)。