Thank you for your answer, Sam.

1) does not really capture it, and 2) is a proof of concept that hasn't been
updated in almost a year. But it did give me a good idea: use Typed Racket 
and
have the type system work for me.

  (struct (N) D ([real : N] [dual : N]))
  (define-type (Dual-Number N) (U N (D N)))

Now a dual number is either an `N` (whatever an `N` is) or a pair of two 
`N`s.
My next idea was to implement dual number multiplication like this:

  (: dual-* (∀ (N) (→ (Dual-Number N) (Dual-Number N) (→ N N N) (→ N N N) 
(Dual-Number N))))
  (define (dual-* d1 d2 * +)
    (cond
      [(and (D? d1) (D? d2))
       (D (* (D-real d1)
             (D-real d2))
          (+ (* (D-real d1)
                (D-dual d2))
             (* (D-dual d1)
                (D-real d2))))]
      [(D? d1) (D (* d2 (D-real d1)) (* d2 (D-dual d1)))]
      [(D? d2) (D (* d1 (D-real d2)) (* d1 (D-dual d2)))]
      [else (* d1 d2)]))

This captures the rule of multiplication of dual numbers in a generic way. 
For
a particular type of dual number one then has to provide the meaning of `+` 
and
`*` for the underlying `N`. So in case of dual vectors one could define

    (define-type Dual-Vector (DualNumber (Vector3 Real)))
    (: dual-vector-product (→ Dual-Vector Dual-Vector Dual-Vector))
    (define (dual-vector-product dv1 dv2)
      (dual-* dv1 dv2 vector3-* vector3-+))

There is a problem with `dual-*` though: The predicate `D?` has type `(-> 
Any
Boolean : (D Any))`, and thus `D-real` and `D-dual` will return an object of
type `Any` rather than `N`, even though the type annotation for `dual-*` 
makes
it clear that the type would have to be `N`. Here is a simpler form of the
function (obviously wrong math, I just want to get the types right):

  (: dual-* (∀ (N) (→ (Dual-Number N) (Dual-Number N) (→ N N N) (→ N N N) 
(Dual-Number N))))
  (define (dual-* d1 d2 * +)
    (cond
      [(D? d1)
       (D 
         (D-real d1) 
         (D-dual d1))]
      [else (D d1 d1)]))

When I try to enter the module I get the following error:

  > ,enter "source/types/dual-number.rkt"
  source/types/dual-number.rkt:30:5: Type Checker: Polymorphic function 
`D1' could not be applied to arguments:
  Argument 1:
    Expected: N
    Given:    Any
  Argument 2:
    Expected: N
    Given:    Any
  
  Result type:     (D N)
  Expected result: (U (D N) N)
  
    in: (D (D-real d1) (D-dual d1))


On Sunday, February 4, 2018 at 3:26:28 PM UTC+1, Sam Tobin-Hochstadt wrote:
>
> A few answers: 
>
> 1. Use struct subtyping to give a type that includes both kinds: 
>     (struct dual ()) 
>     (struct quaternion dual (scalar vector)) 
>     (struct dual-quaternon dual (real dual)) 
>
> 2. Use a library that supports algebraic data types, such as 
> https://pkgs.racket-lang.org/package/datatype 
>
> Sam 
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to