Haskell Linear+AD:如何为Forward适配Metric以使用diff函数?
解决ad包中Quaternion函数微分的问题
我明白你遇到的困境:想用ad的diff处理依赖quadrance的四元数函数,但Forward类型没有Metric实例,而且Metric的kind是* -> *,没法直接给Forward的子类型挂这个实例。其实不用执着于Metric约束,咱们换个思路就能实现微分功能,下面是具体方案:
方案1:手动替换Metric依赖,实现四元数专属版本
既然quadrance对于四元数来说本质是各分量的平方和,咱们可以直接针对Quaternion实现这个操作,摆脱Metric的通用约束,这样就能适配ad的自动微分类型了。
举个例子,假设你原来的函数是这样的:
import Numeric.AD import Data.Quaternion -- 假设用的是标准四元数库 myQuatFunc :: Metric a => Quaternion a -> Quaternion a myQuatFunc q = q * pure (quadrance q)
咱们把它改成不依赖Metric的版本:
-- 专门给四元数实现quadrance quadranceQuat :: Num a => Quaternion a -> a quadranceQuat (Quaternion w x y z) = w^2 + x^2 + y^2 + z^2 myQuatFunc' :: Num a => Quaternion a -> Quaternion a myQuatFunc' q = q * pure (quadranceQuat q)
现在这个myQuatFunc'就能直接用diff处理了——因为Forward类型有Num实例,而Quaternion (Forward a)也会继承Num实例(只要你定义了Quaternion的Num实例),ad的自动微分系统能完美追踪这些操作。
方案2:用新类型包装Forward,间接实现Metric兼容(可选)
如果你不想改动原有的通用函数,可以把Forward包装成新类型,给这个新类型实现Metric实例。不过要注意Metric的kind是* -> *,所以新类型得是类型构造子:
newtype ForwardMetric a = ForwardMetric (Forward a) instance Num a => Metric ForwardMetric where quadrance (ForwardMetric f) = let (Quaternion (Forward w) (Forward x) (Forward y) (Forward z)) = unForward f in w^2 + x^2 + y^2 + z^2
不过这种方式需要你了解Forward的内部结构,相对麻烦,不如方案1直接高效。
核心思路总结
你不需要执着于给Forward加Metric实例,关键是让你的函数操作能被ad的自动微分系统追踪。ad已经给Forward、Reverse等类型实现了Num、Fractional等基础类型类,只要你的四元数函数基于这些基础操作实现,就能顺利用diff计算微分。
内容的提问来源于stack exchange,提问作者Charles Durham
相关产品推荐
相关产品推荐

