2012-03-28 16 views
12

Double -> Double関数をとり、その数学的導関数を返す関数を定義しようとしています。私は、次の操作を実行しようとしている:ハスケルの関数の等価性

der :: (Double -> Double) -> (Double -> Double) 
der f 
    | f == exp = exp 
    | otherwise = undefined 

が、Haskellは==Double -> Double上の値をサポートしていません。ハスケルで私がやろうとしていることは不可能ですか?

+0

'f '(x)=(f(x + dx) - f(x))/ dx'または自動微分を使って数値的に行うことができます。あなたがしようとしているのは、Turing-Complete言語の一般的なケースでは不可能です。 –

答えて

20

はい、あなたはしようとしていることは、Haskellでは不可能であり、一般的には:すべての可能な入力が同じであるかどうかを判断することです。停止問題。

Doubleをシミュレートする(つまり同じインスタンスを使用するため、代わりに使用できる)カスタムタイプを使用して周囲を乗り越えることができますが、数値に評価する代わりに、関数が行う操作の抽象的な表現を構成します。 Exprは、数学的関数定義f(x) = ...の右側を表す。

diff X = Const 1 
diff (Const _) = Const 0 
diff (Plus a b) = Plus (diff a) (diff b) 
diff (Exp a) = Mult (diff a) (Exp a) 
... 

全てを持つ:

fromFunction :: Floating a => (a -> a) -> Expr 
fromFunction f = f X 

toFunction :: Expr -> (Double -> Double) 
toFunction X = \x -> x 
toFunction (Const a) = const a 
toFunction (Plus a b) = \x -> (toFunction a x) + (toFunction b x) 
... 

あなたはまた、式を差別化機能diff :: Expr -> Exprを定義することができます。

data Expr = X | Const Double | 
      Add Expr Expr | Mult Expr Expr | 
      Negate Expr | Inverse Expr | 
      Exp Expr | Log Expr | Sin Expr | ... 
     deriving (Show, Eq) 

instance Num Expr where 
    (+) = Add 
    (*) = Mult 
    ... 
instance Fractional Expr where 
    recip = Inverse 
    ... 
instance Floating Expr where 
    pi = Const pi 
    exp = Exp 
    log = Log 
    sin = Sin 
    ... 

その後、あなたは機能とExpr sの間で変換する変換関数を定義することができますこれらの部分は、(いくつかの)機能を区別できることを意味するはずです。

f x = sin x + cos x * exp x 
f' = toFunction . diff . fromFunction $ f 

警告:Exprの完全なEqインスタンスを定義

  • これは一般的に動作しません、
  • は(それが基本的であるため、それは、停止問題と等価であるトリッキーであります2つの関数が等しいかどうかを調べる)、
  • このコードは実際にテストされていません。
  • 実行時に再構築が行われるため、結果として得られる関数は非常に遅い可能性が高くなります。
+2

これが一般的であるためには、ただ一つの 'X'comstructor以上のものが必要です。実際、 'Eq'インスタンスはトリッキーです。私はこれを試したことがありますが、私の平等チェックは、見過ごすことのできない時間に終了しませんでした。 (∂/∂x(a + x)/ sin x)である。 – leftaroundabout

+1

Exprデータ型に実際に追加する関数に応じて、停止問題と同等である場合とそうでない場合があります。場合によっては、式を正規化して同等かどうかを確認することができます。あるいは、ある意味では、通常のフォームを計算するのと同等の書き換えシステムを作ることができます。これは、toFunctionで評価された2つの式が等しいかどうかを判断することができます。 – danr

11

関数の等価性は拡張的でなければならないため、一般的に等価性のテストは不可能です。すなわち、すべての引数に対して同じ結果を返す場合、2つの関数が等しいとします。

しかし、異なる型を使用するHaskellで派生物を定義する他の方法があります。例えば、Automatic Differentiation,simpler version of AD

+0

+1 - しかし、デリバティブを定義する他の方法についての詳細は良いでしょう。 –

+0

私は数値の差別化に興味がありません。 –

+5

それは数値の区別ではなく、それはそれとは非常に異なっています。これは数字でも象徴的でもなく、3番目の不思議な選択肢です。 :) – augustss