3 ms·
One of my favourite Haskell "one-liners" is combining the AD package with Number.Symbolic: {-# LANGUAGE ImportQualifiedPost #-} module Module_1663
by sordina 4y ago
One of my favourite Haskell "one-liners" is combining the AD package with Number.Symbolic:
{-# LANGUAGE ImportQualifiedPost #-}
module Module_1663406024_9206 where
import Numeric.AD qualified as Ad
import Data.Number.Symbolic qualified as Sym
-- >>> f x = x^2 + 3 * x
-- >>> Ad.diff f 1
-- >>> Ad.diff f (Sym.var "a")
-- 5
-- 3+a+a
-- >>> Ad.diff sin pi
-- >>> Ad.diff sin (Sym.var "a")
-- -1.0
-- cos a
The package authors did not need to coordinate to make this possible which is pretty wild.
Saw it first here: https://twitter.com/GabriellaG439/status/647601518871359489 https://twitter.com/GabriellaG439/status/647601518871359489
and https://www.reddit.com/r/haskell/comments/3r75hq/comment/cwmqphe/?utm_source=share&utm_medium=web2x&context=3 https://www.reddit.com/r/haskell/comments/3r75hq/comment/cwm...
- cryptonector 4y ago> The package authors did not need to coordinate to make this possible which is pretty wild. It works because `f` is polymorphic. The type of its `x` argument is not constrained in `f`'s definition, so you can plug in any `x` of any type you want provided that `x`'s type implements the methods used in `f`'s definition. With the `Dual` scheme you get to use as `x` a "dual" of `y` (`f x`, for some `f`) and `y'`, and then you get an `f` applied to that `x` where the actual `f` is parameterized by the actual `x`'s type, and so the methods called by `f` are those that apply to `x`'s type. So instead of the traditional numeric addition and multiplication, you'd get the "dual" addition and multiplication, and then everything "chains" through and you end up with `diff f x` being the `y'` in the dual of `y` and `y'` (you don't care about the `y`, just the `y'` because you want the `diff` -- the differential or derivative). It's brilliant.
- magicalhippo 4y agoI still don't get how sin ends up as cos, without any coordination.
- krastanov 4y agoPresumably the Ad package has a list of known derivatives. The Sym package now "automatically" uses it, without ever having to have known of it. The "coordination" is that they both use the "symbol" sin to refer to the idea of sine function.
- magicalhippo 4y agoRight, I was confused because for some reason I imagined "sin" coming from the symbolic library, but I'm assuming it's just built-in so AD knows about.
- cryptonector 4y agoThe `sin` function comes from this bit at the end of TFA: instance VectorSpace d => Floating (Dual d) where pi = D pi zero exp (D u u') = D (exp u) (scale (exp u) u') log (D u u') = D (log u) (scale (log u) u') --->sin (D u u') = D (sin u) (scale (cos u) u') cos (D u u') = D (cos u) (scale (-sin u) u') sinh (D u u') = D (sinh u) (scale (cosh u) u') cosh (D u u') = D (cosh u) (scale (sinh u) u') and the `sin` function on the right-hand side comes from `Float`, since `Float` is the type of the argument `u` in `sin u` in `D (sin u) (scale (cos u) u')`.
- krastanov 4y agoNot quite. This subthread is about the extremely short, one-line implementation mentioned here https://news.ycombinator.com/item?id=32882825 https://news.ycombinator.com/item?id=32882825 (which merges two unrelated modules (autodiff and symbolic) and uses autodiff to implement symbolic differentiation). Your comment is true for the original 38-line implemention of autodiff at the very top of the thread, but not in this subthread. The 38-line implementation is similar to the aforementioned autodiff module though.
- cryptonector 4y ago