我一直试图通过编写一个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
中使用时。但是当我尝试在GHCi中键入一个像Vec2 (3,4) <*> 5
这样的简单表达式时,它会报告(Num xx)
类型变量是不明确的。这对我来说很奇怪......在这种情况下我错过了什么? Haskell应该能够为文字选择相同的任意类型,以使类型表达式起作用(就像在works
函数中一样)。
答案 0 :(得分:1)
尝试写
Vec2 (3,4 :: Int) <*> (5 :: Int)
Vec2 (3,4) <*> 5
3,4 ::Num a
并不保证5 :: Num b
和a
具有相同的b
和{{1}}