不可推演关系
Not deducible relationship
为什么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 代数数据结构,其中组件可以是任何数字。
(<.>) :: Num b => a -> a -> b
以上意味着 (<.>)
能够生成 任何 类型的数字,该函数的 caller 可能需要。
比如x,y
是Vec2 Double
,那么x <.> y
就可以调用returnInteger
。然后编译器抱怨它在发布实例中的实现不够通用,因为它 returns Double
s 而不是调用者可能选择的 any 类型。
我认为这不是该代码旨在建模的内容。
您可能想要切换到多参数 class(您需要启用一些扩展,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
正如@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
另一种选择是使用具有函数依赖性的多参数类型类,但我认为这里更复杂。
为什么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 代数数据结构,其中组件可以是任何数字。
(<.>) :: Num b => a -> a -> b
以上意味着 (<.>)
能够生成 任何 类型的数字,该函数的 caller 可能需要。
比如x,y
是Vec2 Double
,那么x <.> y
就可以调用returnInteger
。然后编译器抱怨它在发布实例中的实现不够通用,因为它 returns Double
s 而不是调用者可能选择的 any 类型。
我认为这不是该代码旨在建模的内容。
您可能想要切换到多参数 class(您需要启用一些扩展,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
正如@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
另一种选择是使用具有函数依赖性的多参数类型类,但我认为这里更复杂。