函数依赖的模糊类型

时间:2013-02-04 17:21:18

标签: haskell ghc

在haskell 功能依赖 wiki中:

鉴于这些定义:

data Vector = Vector Int Int deriving (Eq, Show)
data Matrix = Matrix Vector Vector deriving (Eq, Show)
instance Num Vector where
  Vector a1 b1 + Vector a2 b2 = Vector (a1+a2) (b1+b2)
  Vector a1 b1 - Vector a2 b2 = Vector (a1-a2) (b1-b2)
  {- ... and so on ... -}

instance Num Matrix where
  Matrix a1 b1 + Matrix a2 b2 = Matrix (a1+a2) (b1+b2)
  Matrix a1 b1 - Matrix a2 b2 = Matrix (a1-a2) (b1-b2)
  {- ... and so on ... -}
class Mult a b c where
  (*) :: a -> b -> c

instance Mult Matrix Matrix Matrix where
  {- ... -}

instance Mult Matrix Vector Vector where
  {- ... -}

我无法理解为什么会出现含糊不清的类型:

m1, m2, m3 :: Matrix
(m1 * m2) * m3              -- type error; type of (m1*m2) is ambiguous

显然,当 m1 m2 Matrix 时,唯一可能的返回类型是 Matrix ,即应用instance Mult Matrix Matrix Matrix

2 个答案:

答案 0 :(得分:6)

问题在于类型类声明

class Mult a b c where
  (*) :: a -> b -> c

通过对两个参数应用(*),您无法确定结果的类型。假设您有两个实例:

instance Mult Int Int Int where ...
instance Mult Int Int Integer where ...

然后2 * 4可以是Int类型,也可以是Integer类型。

现在你可以争辩说你只有一个实例,所以编译器不应该抱怨。但是Haskell类型的类存在于开放世界中。您始终可以添加更多实例,并且不得在其他地方破坏代码。因此,即使您只有一个实例,另一个库中的其他人也可以添加另一个实例。而且,你有两个库,每个都在工作,但却失败了。这显然是一种情感。 请参阅Real World Haskell中的Living in an open world

因此,类型类中函数的返回类型通常必须从其参数派生。这正是函数依赖性的用途。如果你宣布

class Mult a b c | a b -> c where

然后编译器总是可以告诉(*)的返回类型。

答案 1 :(得分:1)

因为你忘记了所有其他的可能性,例如

 instance Mult Matrix Matrix Vector where
 instance Mult Vector Matrix Vector where
 instance Mult Float Matrix Float where
 instance Mult Matrix Matrix Float where  -- etc.

 a :: Vector
 a = (m1 >< m2:: Vector) >< m3

 b :: Float
 b = (m1 >< m2:: Float) >< m3

向类定义添加功能依赖:

instance Mult a b c | a b -> c

意味着

instance Mult Matrix Matrix Matrix

决定两个矩阵的问题和那个

instance Mult Matrix Matrix Vector
instance Mult Matrix Matrix Float

被排除在外,因为它们提供了另一种查看“MatrixMatrix的产品”的方法。因此,您发现的直观事态就是您可以获得的功能依赖性。

如果功能依赖性是这样制定的:

 instance Mult a b c | b -> a c

这也会允许您声明的两个实例,

 instance Mult Matrix Matrix Matrix where
 instance Mult Matrix Vector Vector where

但排除我想象的其他人,Matrix位置都b(因为他们不得不这样做,因为在暧昧的例子中m3被解释为{{1}而不是矩阵乘积的结果。