创建一个类型类,在haskell中返回该类型类的另一个实例

Thi*_*one 2 math haskell functional-programming

我正在尝试创建一个系统来派生符号函数,我遇到了一个问题:

我有一个表达式的类型类Exp,它定义了一个派生函数:

class Exp e where 
    derivative :: (Exp d) => e -> d
Run Code Online (Sandbox Code Playgroud)

我希望该类有几个实例:

data Operator a b = a :* b | a :+ b

instance (Exp a, Exp b) => Exp (Operator a b)  where
    derivative (f :* g) = ((derivative f) :* g) :+ (f :* (derivative g)) --The derivative of the multiplication of two expressions 
    derivative (f :+ g) = derivative f :+ derivative g --The derivative of the addition of two expressions

instance Exp Double where
    derivative a = (0 :: Double)  --The derivative of a constant value is 0


instance Exp Char where
    derivative c = (1 :: Double) --The derivative of just a variable is one
Run Code Online (Sandbox Code Playgroud)

我用ghci编译得到的是:

math.hs:19:21: error:
• Couldn't match expected type ‘d’ with actual type ‘Double’
  ‘d’ is a rigid type variable bound by
    the type signature for:
      derivative :: forall d. Exp d => Double -> d
    at math.hs:19:5
• In the expression: (0 :: Double)
  In an equation for ‘derivative’: derivative a = (0 :: Double)
  In the instance declaration for ‘Exp Double’
• Relevant bindings include
    derivative :: Double -> d (bound at math.hs:19:5)

math.hs:22:21: error:
• Couldn't match expected type ‘d’ with actual type ‘Double’
  ‘d’ is a rigid type variable bound by
    the type signature for:
      derivative :: forall d. Exp d => Char -> d
    at math.hs:22:5
• In the expression: (1 :: Double)
  In an equation for ‘derivative’: derivative c = (1 :: Double)
  In the instance declaration for ‘Exp Char’
• Relevant bindings include
    derivative :: Char -> d (bound at math.hs:22:5)

math.hs:28:27: error:
• Couldn't match expected type ‘d’
              with actual type ‘Operator (Operator a0 b) (Operator a b0)’
  ‘d’ is a rigid type variable bound by
    the type signature for:
      derivative :: forall d. Exp d => Operator a b -> d
    at math.hs:27:5
• In the expression: derivative f :+ derivative g
  In an equation for ‘derivative’:
      derivative (f :+ g) = derivative f :+ derivative g
  In the instance declaration for ‘Exp (Operator a b)’
• Relevant bindings include
    g :: b (bound at math.hs:28:22)
    f :: a (bound at math.hs:28:17)
    derivative :: Operator a b -> d (bound at math.hs:27:5)
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么我的实例减速问题?每个中的导数总是解析为Exp类型约束所需的实例derivative,那么为什么它不能匹配类型呢?

yep*_*ons 5

当你写作

class Exp e where 
    derivative :: (Exp d) => e -> d
Run Code Online (Sandbox Code Playgroud)

你声明类中的任何类型eExp应该有一个函数derivative :: e -> d.请注意,e这是一个非常具体的类,但d只是说是在Exp.它几乎是一种任意类型.因此,您正在尝试定义一个函数,该函数在给定参数的情况下返回属于的任意类型的值Exp

选择d留给编译器根据上下文,像fromInteger.所以你不能说"每一个e有一个d属于Exp这样derivative将返回d",你说"每个e d属于Exp是这样的,derivative将返回d".如果你想说前者,你可能不得不使用多参数化类和函数依赖(指定输出类型由输入类型唯一确定).

如果我们替换e某些特定类型,您尝试实现以下内容:

derivative :: Exp d => Double -> d
derivative = (0::Double)
Run Code Online (Sandbox Code Playgroud)

这不是你能做的事情,因为不是所有人Exp都是双打.说,Operator Double Double(其中Exp)显然不是一个Double.更具有同样问题的人为例子:

derivative :: Double -> a
derivative = (0::Double)
Run Code Online (Sandbox Code Playgroud)