Numeric.AD - 类型变量脱离其作用域
Numeric.AD - type variable escaping its scope
我正在尝试在 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
没有产生任何错误。
cost ref plant
具有 [a] -> a
类型,其中 a
与 optimize
的签名相同 a
optimize :: (RealFloat a) => Reference a -> Plant a -> [a] -> [[a]]
^ ^
| ------------
------------------v v
optimize ref plant initialInputs = gradientDescent (cost ref plant) initialInputs
^ ^
----------------------- |
v v---------------
cost :: (RealFloat a) => Reference a -> Plant a -> [a] -> a
cost = ...
但是gradientDescent
的类型是
gradientDescent :: (Traversable f, Fractional a, Ord a) =>
(forall s. Reifies s Tape => f (Reverse s a) -> Reverse s a) ->
f a -> [f a]
gradientDescent
的第一个参数需要能够接受(对于 any s
)[Reverse s a]
和 return一个Reverse s a
,但是cost ref plant
只能取[a]
一个return一个a
.
由于Reference
和Plant
都是Functor
,你可以将ref
和plant
从Reference a
和[=32转换为ref
和plant
=] 到 Reference (Reverse s a)
和 Plant (Reverse s a)
通过 fmap
ing auto
.
optimize :: (RealFloat a) => Reference a -> Plant a -> [a] -> [[a]]
optimize ref plant initialInputs = gradientDescent (cost (fmap auto ref) (fmap auto plant)) initialInputs
我正在尝试在 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
没有产生任何错误。
cost ref plant
具有 [a] -> a
类型,其中 a
与 optimize
a
optimize :: (RealFloat a) => Reference a -> Plant a -> [a] -> [[a]]
^ ^
| ------------
------------------v v
optimize ref plant initialInputs = gradientDescent (cost ref plant) initialInputs
^ ^
----------------------- |
v v---------------
cost :: (RealFloat a) => Reference a -> Plant a -> [a] -> a
cost = ...
但是gradientDescent
的类型是
gradientDescent :: (Traversable f, Fractional a, Ord a) =>
(forall s. Reifies s Tape => f (Reverse s a) -> Reverse s a) ->
f a -> [f a]
gradientDescent
的第一个参数需要能够接受(对于 any s
)[Reverse s a]
和 return一个Reverse s a
,但是cost ref plant
只能取[a]
一个return一个a
.
由于Reference
和Plant
都是Functor
,你可以将ref
和plant
从Reference a
和[=32转换为ref
和plant
=] 到 Reference (Reverse s a)
和 Plant (Reverse s a)
通过 fmap
ing auto
.
optimize :: (RealFloat a) => Reference a -> Plant a -> [a] -> [[a]]
optimize ref plant initialInputs = gradientDescent (cost (fmap auto ref) (fmap auto plant)) initialInputs