This is an unfortunately common pitfall -- if you instantiated N with something that includes a dual number, then the type error would be pointing to a real bug. If
Sam On Feb 5, 2018 7:26 AM, "HiPhish" <hiph...@openmailbox.org> wrote: > 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 racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- 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 racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.