ad icon indicating copy to clipboard operation
ad copied to clipboard

nesting: diff (\x -> diff (*x) 1) 1

Open barak opened this issue 7 years ago • 5 comments

Was showing off nesting, simplest example I could think of, oops.

tldr: ad 4.3.2.1, ghc 8.0.1, diff (\x -> diff (*x) 1) 1 gets a type error.

$ cabal update
Downloading the latest package list from hackage.haskell.org
$ cabal install --user ad
Resolving dependencies...
Downloading base-orphans-0.5.4...
...
Installed free-4.12.4
Downloading ad-4.3.2.1...
Configuring ad-4.3.2.1...
Building ad-4.3.2.1...
Installed ad-4.3.2.1
$ ghci
GHCi, version 8.0.1: http://www.haskell.org/ghc/  :? for help
Prelude> :m + Numeric.AD
Prelude Numeric.AD> diff (*2) 1
2
Prelude Numeric.AD> diff sin 0
1.0
Prelude Numeric.AD> diff (\x -> diff (*x) 1) 1

<interactive>:6:20: error:
    • Occurs check: cannot construct the infinite type:
        a ~ AD s (Numeric.AD.Internal.Forward.Forward a)
      Expected type: AD
                       s1
                       (Numeric.AD.Internal.Forward.Forward
                          (AD s (Numeric.AD.Internal.Forward.Forward a)))
        Actual type: AD s (Numeric.AD.Internal.Forward.Forward a)
    • In the second argument of ‘(*)’, namely ‘x’
      In the first argument of ‘diff’, namely ‘(* x)’
      In the expression: diff (* x) 1
    • Relevant bindings include
        x :: AD s (Numeric.AD.Internal.Forward.Forward a)
          (bound at <interactive>:6:8)
        it :: a (bound at <interactive>:6:1)

This happens even without nesting.

> diff (pi*) 1
3.141592653589793
> (\x -> diff (x*) 1) pi
error: ...
> let x=pi in diff (x*) 1
3.141592653589793

and yes, I know auto makes it okay

Prelude Numeric.AD> diff (\x -> diff (auto x*) 2) 3
1
Prelude Numeric.AD> (\x -> diff (auto x*) 2) 3
3

But it's still a pretty big wart on an otherwise lovely countenance.

barak avatar Dec 04 '16 10:12 barak

I don't know if this is helpful, but this works fine if you use the diff from Numeric.AD.Rank1.Forward

alang9 avatar May 25 '17 16:05 alang9

Not entirely.

Prelude Numeric.AD.Rank1.Forward> :t diff
diff :: Num a => (Forward a -> Forward a) -> a -> a

Prelude Numeric.AD.Rank1.Forward> diff (\x -> diff (x*) 2) 3
<interactive>:10:13: error:
    • Occurs check: cannot construct the infinite type: a ~ Forward a
    • In the expression: diff (x *) 2
      In the first argument of ‘diff’, namely ‘(\ x -> diff (x *) 2)’
      In the expression: diff (\ x -> diff (x *) 2) 3
    • Relevant bindings include
        x :: Forward a (bound at <interactive>:10:8)
        it :: a (bound at <interactive>:10:1)

Prelude Numeric.AD.Rank1.Forward> diff (\x -> diff (auto x*) 2) 3
1

barak avatar May 29 '17 14:05 barak

I don't see this issue ever going away with Haskell's notion of (*) :: Num a => a -> a -> a requiring both sides to have the same type. We can work around it by offering folks auto or (*^) and (^*), but without a custom numeric prelude that blurs the lines between scalars and vectors and then only infers forward not backwards, and is literally incompatible with the desugaring applied to integers, and so is incompatible with literally all other haskell numerics this seems fundamentally unsolvable.

ekmett avatar Feb 15 '21 04:02 ekmett

What would the types of the *^ be?

On Sun, Feb 14, 2021 at 11:47 PM Edward Kmett [email protected] wrote:

I don't see this issue ever going away with Haskell's notion of () :: Num a => a -> a -> a requiring both sides to have the same type. We can work around it by offering folks auto or (^) and (^*), but without a custom numeric prelude that blurs the lines between scalars and vectors and then only infers forward not backwards, and is literally incompatible with the desugaring applied to integers, and so is incompatible with literally all other haskell numerics this seems fundamentally unsolvable.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ekmett/ad/issues/60#issuecomment-778934674, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAABBQUZ33YVC775QMOIPIDS7CRORANCNFSM4CYOG26Q .

cartazio avatar Feb 15 '21 13:02 cartazio

(*^) multiplies whatever the 'scalar' type is for the mode, treating the ad type as an algebra over the basic scalar. It already exists inside Numeric.AD.Mode (or Jacobian). basically it is equivalent to x *^ y = auto x * y

ekmett avatar Feb 15 '21 13:02 ekmett