如何区分积分与向量空间库(haskell)

The*_*MAN 5 haskell

当使用矢量空间包进行衍生塔(参见衍生塔)时,我遇到了区分积分的需要.从数学来看,很明显如何实现这一点:

f(x) = int g(y) dy from 0 to x
Run Code Online (Sandbox Code Playgroud)

有功能

g : R -> R
Run Code Online (Sandbox Code Playgroud)

例如.

关于x的导数将是:

f'(x) = g(x)
Run Code Online (Sandbox Code Playgroud)

我试图通过首先定义一个类"集成"来获得这种行为

class Integration a b where
--standard integration function
integrate :: (a -> b) -> a -> a -> b
Run Code Online (Sandbox Code Playgroud)

一个基本的例子是

instance  Integration Double Double where
  integrate f a b = fst $ integrateQAGS prec 1000 f a b
Run Code Online (Sandbox Code Playgroud)

integrateQAGSHMATRIX

问题来自值b代表衍生品塔:

instance Integration Double (Double :> (NC.T Double)) where
  integrate = integrateD
Run Code Online (Sandbox Code Playgroud)

NC.T来自Numeric.Complex(数字前奏曲).该函数integrateD定义如下(但错误):

integrateD ::(Integration a b, HasTrie (Basis a), HasBasis a, AdditiveGroup b) =>  (a -> a :> b) -> a -> a -> (a :> b)
integrateD f l u = D (integrate (powVal . f) l u) (derivative $ f u)
Run Code Online (Sandbox Code Playgroud)

函数不返回我想要的东西,它导出的是被积函数,但不是积分函数.问题是,我需要一个返回的线性地图f u.的a :> b定义如下:

data a :> b = D { powVal :: b, derivative :: a :-* (a :> b) }
Run Code Online (Sandbox Code Playgroud)

我不知道如何定义derivative.任何帮助将不胜感激,谢谢

编辑:

我忘了提供以下实例Integration Double (NC.T Double):

instance  Integration Double (NC.T Double) where
  integrate f a b = bc $ (\g -> integrate g a b) <$> [NC.real . f, NC.imag . f]
      where bc (x:y:[]) = x NC.+: y
Run Code Online (Sandbox Code Playgroud)

我可以举出一个我的意思的例子:假设我有一个功能

f(x) = exp(2*x)*sin(x)

>let f = \x -> (Prelude.exp ((pureD 2.0) AR.* (idD x))) * (sin (idD x)) :: Double :> Double 
Run Code Online (Sandbox Code Playgroud)

(AR.*)表示从Algebra.Ring(数字前奏)乘法

我可以轻松地将此功能与上述功能集成integrateD:

>integrateD f 0 1 :: Double :> Double
D 1.888605715258933 ...
Run Code Online (Sandbox Code Playgroud)

当我看一下f的衍生物时:

f'(x) = 2*exp(2*x)*sin(x)+exp(2*x)*cos(x)
Run Code Online (Sandbox Code Playgroud)

在评价这0pi/2我得到1一些价值:

> derivAtBasis (f 0.0) ()
D 1.0 ...

> derivAtBasis (f (pi AF./ 2)) ()
D 46.281385265558534 ...
Run Code Online (Sandbox Code Playgroud)

现在,在导出积分时,我得到函数的推导而f不是它在上界的值

> derivAtBasis (integrate f 0 (pi AF./ 2)) ()
D 46.281385265558534 ...
Run Code Online (Sandbox Code Playgroud)

但我希望:

> f (pi AF./ 2)
D 23.140692632779267 ...
Run Code Online (Sandbox Code Playgroud)

The*_*MAN 0

我终于找到了我的问题的解决方案。解决问题的关键是>-<向量空间包中的函数,它代表链式法则。

所以,我定义了一个integrateD'这样的函数:

integrateD' :: (Integration a b, HasTrie (Basis a), HasBasis a, AdditiveGroup b , b ~ Scalar b, VectorSpace b) => (a -> a :> b) -> a -> a -> (a:>b) -> (a :> b)
integrateD' f l u d_one =  ((\_ -> integrate (powVal . f) l  (u)) >-< (\_ ->  f u)) (d_one)
Run Code Online (Sandbox Code Playgroud)

d_one意味着导数变量及其导数必须为 1。通过此函数,我现在可以创建一些实例,例如

instance Integration Double (Double :> Double) where
integrate f l u = integrateD' f l u (idD 1)
Run Code Online (Sandbox Code Playgroud)

instance Integration ( Double) (Double :> (NC.T Double)) where
integrate f l u = liftD2 (NC.+:) (integrateD' (\x -> NC.real <$>> f x) l u (idD 1.0 :: Double :> Double)) (integrateD' (\x -> NC.imag <$>> f x) l u (idD 1.0 :: Double :> Double))
Run Code Online (Sandbox Code Playgroud)

不幸的是我不能使用integrateD开箱即用的复杂值,我必须使用liftD2. 原因似乎是idD功能,不知道是否有更优雅的解决方案。

当我查看问题中的示例时,我现在得到了我想要的解决方案:

*Main> derivAtBasis (integrateD' f 0 (pi AF./ 2) (idD 1.0 :: Double :> Double )) ()
D 23.140692632779267 ...
Run Code Online (Sandbox Code Playgroud)

或通过使用实例:

*Main> derivAtBasis (integrate f 0 (pi AF./ 2)) ()
D 23.140692632779267 ...
Run Code Online (Sandbox Code Playgroud)