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.