だから私はデュアルナンバークラスを持っています:
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)
ここで、数値関数を受け取り、その導関数を数値関数として与える関数を書きたいと思います。(自動微分を使用)。
これが私が思いついたものです:
{-# LANGUAGE FlexibleContexts #-}
autoDiff :: Floating a => (Dual a -> Dual a) -> a -> a
autoDiff f = dualPart . f . (flip (:+) 1)
たとえばsin、次のようになります。
*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たが、ジェネリック関数を取得できず、デュアルを突き刺してジェネリック関数を返すことができません。
では、どのように反復autoDiffしてより高い導関数を取得できますか?Haskellの型システムでも可能ですか?