【发布时间】:2015-08-15 17:23:36
【问题描述】:
我正在尝试在 Haskell 中使用 automatic differentiation 来解决非线性控制问题,但在让它工作时遇到了一些问题。我基本上有一个cost 函数,应该在给定初始状态的情况下对其进行优化。类型有:
data Reference a = Reference a deriving Functor
data Plant a = Plant a deriving Functor
optimize :: (RealFloat a) => Reference a -> Plant a -> [a] -> [[a]]
optimize ref plant initialInputs = gradientDescent (cost ref plant) initialInputs
cost :: (RealFloat a) => Reference a -> Plant a -> [a] -> a
cost = ...
这会导致以下错误消息:
Couldn't match expected type `Reference
(Numeric.AD.Internal.Reverse.Reverse s a)'
with actual type `t'
because type variable `s' would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
Data.Reflection.Reifies s Numeric.AD.Internal.Reverse.Tape =>
[Numeric.AD.Internal.Reverse.Reverse s a]
-> Numeric.AD.Internal.Reverse.Reverse s a
at test.hs:13:5-50
Relevant bindings include
initialInputs :: [a] (bound at test.hs:12:20)
ref :: t (bound at test.hs:12:10)
optimize :: t -> t1 -> [a] -> [[a]] (bound at test.hs:12:1)
In the first argument of `cost', namely `ref'
In the first argument of `gradientDescent', namely
`(cost ref plant)'
我什至不确定我是否正确理解了错误。是不是ref和plant的类型需要访问s,这在gradientDescent的第一个参数范围内?
是否有可能做到这一点?在寻找解决方案时,我尝试将问题简化为最小示例,发现以下定义会产生类似的错误消息:
optimize f inputs = gradientDescent f inputs
这看起来很奇怪,因为optimize = gradientDescent 不会产生任何错误。
【问题讨论】:
-
Reference和Plant是什么? -
与stackoverflow.com/a/29393417/414413相关,这两个问题都是关于
gradientDescent的第一个参数的类型,答案基本相同,但提示问题的错误不同。 -
Reference和Plant是仿函数。更具体地说,Reference是一个简单的代数数据类型,Plant是来自netwire库的Wire的类型别名。 -
optimize = gradientDescent有效,因为未应用它可以并且将推断出 rank-n 类型。当你像这样扩展它时,必须指定 rank-n 类型,因为它超出了任何类型系统可以推断的范围。
标签: haskell automatic-differentiation