Sí, lo que estás tratando de hacer es imposible en Haskell, y en general: decidir si dos funciones son iguales para todas las entradas posibles (sin solo verificar cada valor de entrada, si eso es posible) es equivalente a resolver el Deteniendo el problema.
Sin embargo, en su caso específico, puede evitarlo, utilizando un tipo personalizado que simula un Double
(es decir, tiene las mismas instancias y, por lo tanto, puede usarse en lugar del mismo) pero en lugar de evaluar a un número, construye una representación abstracta de las operaciones que hace la función. Expr
representa el lado derecho de una definición de función matemática f(x) = ...
.
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
...
A continuación, se pueden definir las funciones de conversión que convierten entre las funciones y Expr
s:
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)
...
También puede definir una función diff :: Expr -> Expr
que diferencia la expresión:
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)
...
Tener toda estas partes deben significar que puede diferenciar (algunas) funciones, por ejemplo
f x = sin x + cos x * exp x
f' = toFunction . diff . fromFunction $ f
Advertencias:
- esto no funcionará en general,
- definir una completa
Eq
instancia para Expr
es complicado (que es equivalente al problema de la parada, ya que es básicamente preguntando si dos funciones son iguales),
- No he probado ninguno de este código,
- the differentiati y la reconstrucción se realizan en tiempo de ejecución, por lo que es muy probable que la función resultante sea muy lenta.
Puedes hacerlo numéricamente usando, 'f '(x) = (f (x + dx) - f (x))/dx' o diferenciación automática. Lo que intenta hacer es imposible en el caso general de los lenguajes Turing-Complete. –