让我说我有:
f :: Double -> Double
f x = 3*x^2 + 5*x + 9
我想计算这个函数的导数并写
derivate f
这样
derivate f == \x -> 6*x + 5
但如何定义derivate
?
derivate :: (a -> a) -> (a -> a)
derivate f = f' -- how to compute f'?
我知道没有本地方法可以做到这一点,但是有一个库可以吗?
我们是否必须依靠“meta”-datatypes来实现这一目标?
data Computation = Add Exp Expr | Mult Expr Expr | Power Expr Expr -- etc
那么,为每个函数创建相应的构造函数是不是很痛苦?但是,数据类型不应表示函数(解析器除外)。
由于其术语重写功能,Pure是一个不错的选择吗?它不也有缺点吗?
列表是否可以承受?
f :: [Double]
f = [3, 5, 9]
derivate :: (a -> [a])
derivate f = (*) <$> f <*> (getNs f)
compute f x = sum $
((*) . (^) x) <$> (getNs f) <*> f
getNs f = (reverse (iterate (length f) [0..]))
Haskell现在看起来依赖于LISP,语法不太合适。等待一起使用的函数和参数完全存储在数据类型中。 此外,它不是很自然。
除了多项式之外,它们似乎不够“灵活”,不能使用derivate
函数,例如单应函数。
现在,例如,我想在游戏中使用衍生品。角色在使用功能的地板上运行,如果地板足够陡峭,我希望他能够滑动。
我还需要为各种目的求解方程。一些例子:
我是宇宙飞船,我想小睡一下。在我睡觉的时候,如果我没有小心翼翼地放置自己,我可能会因为引力而在地球上坠毁。我没有足够的气体远离天体,我也没有地图。
因此,我必须把自己置于这个区域内的物体之间,以便取消它们对我的重力影响的总和。
x
和y
是我的坐标。 gravity
是一个函数,它接收两个对象并在它们之间返回重力的向量。
如果有两个物体,比如地球和月球,除了我之外,我需要做的就是找到要去的地方:
gravity earth spaceship + gravity moon spaceship == (0, 0)
比从头equigravityPoint :: Object -> Object -> Object -> Point
创建新功能更简单,更快捷等。
如果除了我之外还有3个物体,它仍然很简单。
gravity earth spaceship + gravity moon spaceship + gravity sun spaceship == (0, 0)
4和n相同。与equigravityPoint
相比,处理对象列表要简单得多。
其他例子。
我想编写一个射击我的敌人机器人。
如果他只是针对我目前的位置射击,如果我向我跑去,他会得到我,但是如果我跳起来摔倒在他身上,他会想念我的。
一个更智能的机器人就是这样想的:“好吧,他从墙上跳下来。如果我射击目标他现在的子弹将不会得到他,因为他将移动到那时。所以我会预料到他会在哪里在几秒钟内拍摄,以便子弹和他同时到达这一点“。
基本上,我需要能够计算轨迹。例如,对于这种情况,我需要trajectoryBullet == trajectoryCharacter
的解决方案,它给出了线和抛物线相遇的点。
一个不涉及速度的类似且更简单的例子。 我是一个消防员机器人,还有一座建筑物着火了。另一队消防员正在用水枪对抗火灾。我和有人跳了起来。当我的朋友们开水时,我拿着蹦床。 我需要去人们将要去的地方。所以我需要轨迹和方程求解。
答案 0 :(得分:4)
数值导数可以很容易地完成:
derive f x = (f (x + dx) - f (x - dx)) / (2 * dx) where dx = 0.00001
但是,对于符号衍生物,您需要创建一个AST,然后通过匹配和重写AST来实现派生规则。
答案 1 :(得分:2)
我不明白您使用自定义数据类型的问题
data Expr = Plus Expr Expr
| Times Expr Expr
| Negate Expr
| Exp Expr Expr
| Abs Expr
| Signum Expr
| FromInteger Integer
| Var
instance Num Expr where
fromInteger = FromInteger
(+) = Plus
(*) = Times
negate = Negate
abs = Abs
signum = Signum
toNumF :: Num a => Expr -> a -> a
toNumF e x = go e where
go Var = x
go (FromInteger i) = fromInteger i
go (Plus a b) = (go a) + (go b)
...
然后你可以像Int
或Double
一样使用它,一切都会正常工作!您可以定义一个函数
deriveExpr :: Expr -> Expr
然后可以让你定义以下(RankN)函数
derivate :: Num b => (forall a. Num a => a -> a) -> b -> b
derivate f = toNumF $ deriveExpr (f Var)
您可以将其扩展为与数字层次结构的其他部分一起使用。