首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Haskell中实现自动区分?

如何在Haskell中实现自动区分?
EN

Stack Overflow用户
提问于 2018-08-01 20:44:37
回答 1查看 473关注 0票数 2

所以我有一个双数字类:

代码语言:javascript
复制
data Dual a = !a :+ !a
instance [safe] Eq a => Eq (Dual a)
instance [safe] RealFloat a => Floating (Dual a)
instance [safe] RealFloat a => Fractional (Dual a)
instance [safe] RealFloat a => Num (Dual a)
instance [safe] Read a => Read (Dual a)
instance [safe] Show a => Show (Dual a)

现在我想写一个函数,它接受一个数值函数,并给出它的导数作为一个数值函数。(使用自动区分)。

下面是我的想法:

代码语言:javascript
复制
{-# LANGUAGE FlexibleContexts #-}
autoDiff :: Floating a => (Dual a -> Dual a) -> a -> a
autoDiff f = dualPart . f . (flip (:+) 1)

现在以sin为例,下面是我得到的结果:

代码语言:javascript
复制
*AutoDiff> :t sin
sin :: Floating a => a -> a

*AutoDiff> :t autoDiff sin
autoDiff sin :: RealFloat a => a -> a

*AutoDiff> :t autoDiff (autoDiff sin)
autoDiff (autoDiff sin) :: (RealFloat (Dual a), RealFloat a) => a -> a

*AutoDiff> sin 1
0.8414709848078965

*AutoDiff> (autoDiff sin) 1
0.5403023058681398

*AutoDiff> (autoDiff (autoDiff sin)) 1

<interactive>:109:1: error:
    • No instance for (RealFloat (Dual a0)) arising from a use of ‘it’
    • In a stmt of an interactive GHCi command: print it

我不知道错误消息告诉我的是什么。我尝试过使用forall,但我不能接受一个泛型函数,通过它来处理duals,然后返回一个泛型函数。

那么,我如何迭代autoDiff来获得更高的导数,在Haskell的类型系统中,这是可能的吗?

EN

回答 1

Stack Overflow用户

发布于 2018-08-07 04:44:19

您可以尝试:

代码语言:javascript
复制
autoDiff (autoDiff sin)

哈斯克尔说:

代码语言:javascript
复制
No instance for (RealFloat (Dual a0)) arising from a use of ‘it’

现在我们可以问这是从哪里来的,但是让我们写下我们拥有的类型,看看我们是否可以在甚至不查看它所说的内容的情况下解决这个错误:

代码语言:javascript
复制
autoDiff :: Num a => (Dual a -> Dual a) -> a -> a
sin :: Floating a => a -> a

在计算autoDiff sin时,必须使sinDual a -> Dual a统一,因此这需要Floating a

代码语言:javascript
复制
autoDiff sin :: (Floating (Dual a), Num a) => a -> a

现在你想要取这个的autoDiff,同样的事情发生了:

代码语言:javascript
复制
autoDiff (autoDiff sin) :: (Floating (Dual (Dual a)), Num a) => a -> a

现在,当您键入autoDiff (autoDiff sin) 1时,Haskell确定这具有类型(Floating (Dual (Dual a)), Num a) => a,但它需要选择一些a来打印结果。它将先尝试Integer,然后尝试Double,然后将失败。

Haskell正在寻找满足约束Floating (Dual (Dual a))的所有方法,因此它寻找了所有可以为Dual x派生实例的方法,事实证明它需要RealFloat x来做到这一点。因此,现在它已经将约束从Floating (Dual (Dual a))减少到RealFloat (Dual a),事实证明,它无法派生RealFloat (Dual a)的实例,因此它无法编译。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51633624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档