2

だから私はデュアルナンバークラスを持っています:

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の型システムでも可能ですか?

4

1 に答える 1