为什么a
和b
之间的关系无法推断?
class Vector a where
(<.>) :: Num b => a -> a -> b
data Vec2 a
= Vec2 (a, a)
deriving Show
instance Num a => Vector (Vec2 a) where
Vec2 (a, b) <.> Vec2 (c, d) = a * c + b * d
我希望有一个Vec2代数数据结构,其中组件可以是任何数字。
答案 0 :(得分:7)
(<.>) :: Num b => a -> a -> b
以上意味着(<.>)
能够生成该函数可能需要的调用者的任何类型的数字。
例如,如果x,y
为Vec2 Double
,则可以调用x <.> y
返回Integer
。编译器然后抱怨它在发布的实例中的实现不够通用,因为它返回Double
而不是调用者可能选择的任何类型。
我认为这不是该代码的目的。
您可能希望切换到多参数类(您需要启用一些扩展,GHC会告诉您哪些扩展):
class Vector a b where
(<.>) :: a -> a -> b
instance Num a => Vector (Vec2 a) a where
Vec2 (a, b) <.> Vec2 (c, d) = a * c + b * d
由于编译器无法从x <.> y
类型确定x,y
的类型,您可能希望使用
class Vector a b | a -> b where
(<.>) :: a -> a -> b
或者使用类型系列
class Vector a where
type Scalar a
(<.>) :: a -> a -> Scalar a
instance Num a => Vector (Vec2 a) where
type Scalar (Vec a) = a
Vec2 (a, b) <.> Vec2 (c, d) = a * c + b * d
答案 1 :(得分:2)
正如@ chi的回答所说,你的代码并不能使b
依赖a
。为了得到我想你想要的东西,你可以使用一个相关的类型族:
{-# LANGUAGE TypeFamilies #-}
class Vector a where
type Element a
(<.>) :: a -> a -> Element a
data Vec2 a
= Vec2 (a, a)
deriving Show
instance Num a => Vector (Vec2 a) where
type Element (Vec2 a) = a
Vec2 (a, b) <.> Vec2 (c, d) = a * c + b * d
另一种选择是使用具有功能依赖性的多参数类型类,但我认为这里更复杂。