Re: [racket-users] Defining algebraic data types?
That makes perfect sense, thank you. On Tuesday, February 6, 2018 at 12:43:07 AM UTC+1, Sam Tobin-Hochstadt wrote: > The problem is that the definition of `(Dual-Number N)` includes `N`, > and therefore > > (Dual-Number (Dual-Number String)) might either be a (D (D "x" "y") (D > "x" "y")) or just (D "x" "y"). Therefore checking D? can't tell that > you're in the `D` case because both cases could be a `D` case. > > 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.
Re: [racket-users] Defining algebraic data types?
On Mon, Feb 5, 2018 at 6:36 PM, HiPhish wrote: > Why would that be a problem? The caller has to provide a function for > "adding" > and "multiplying" an N, and as long as I define what it means to multiply > and > add strings it shouldn't matter that I'm using a dual number where both > components are strings. The problem is that the definition of `(Dual-Number N)` includes `N`, and therefore (Dual-Number (Dual-Number String)) might either be a (D (D "x" "y") (D "x" "y")) or just (D "x" "y"). Therefore checking D? can't tell that you're in the `D` case because both cases could be a `D` case. Sam > > But I think this is a case of the rectangle-square problem: dual scalars and > a > dual vectors a both a subset of dual quaternions that contain less > information > than their supertype. I guess what I'm really looking for is a way to > "magically" promote objects. > > A quaternion is an object of > > H = {a + bi + cj + dk | a,b,c,d ∈ R}, > > a vector is an object of > > V = {ai + bj + ck | a,b,c ∈ R}, > > but we can also view H as > > H = R × V = {(a, v) | a ∈ R, v ∈ V}. > > The first definition of H is how it is usually defined and written out, but > the > second definition makes it easier to compute the product: > > (p_r, p_v) (q_r, q_v) = (p_r q_r - p_v ⋅ q_v, p_r q_v + q_r p_v + p_v × > q_v). > > So far this is a simple hierarchy. But the set of scalars and the set of > vectors can be embedded in the set of quaternions: > > R → H, a ↦ (a, 0) and V → H, v ↦ (0, v) > > We can also define things like the "quaternion cross product" and > "quaternion > dot product" for quaternions where the scalar part is zero: > > (0, p) × (0, q) := (p, p × q) > (0, p) ⋅ (0, q) := (p ⋅ q, 0) > > I'm starting to think this is becoming a pointless exercise. Maybe I should > just limit myself to "dual quaternions are a pair of quaternions" and > "quaternions are pairs of a scalar and a vector" and forget about the magic > subtyping. > > > On Tuesday, February 6, 2018 at 12:01:42 AM UTC+1, Sam Tobin-Hochstadt > wrote: >> >> I'm not sure how the "If" got there. >> >> But to say more, consider your function: >> >> (: 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)])) >> >> Now you imagine instantiating `N` with things like `(Vector3 Real)`, >> but if we instantiated it instead with `(Dual-Number String)`, then >> you'd have a problem. >> >> 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.
Re: [racket-users] Defining algebraic data types?
Why would that be a problem? The caller has to provide a function for "adding" and "multiplying" an N, and as long as I define what it means to multiply and add strings it shouldn't matter that I'm using a dual number where both components are strings. But I think this is a case of the rectangle-square problem: dual scalars and a dual vectors a both a subset of dual quaternions that contain less information than their supertype. I guess what I'm really looking for is a way to "magically" promote objects. A quaternion is an object of H = {a + bi + cj + dk | a,b,c,d ∈ R}, a vector is an object of V = {ai + bj + ck | a,b,c ∈ R}, but we can also view H as H = R × V = {(a, v) | a ∈ R, v ∈ V}. The first definition of H is how it is usually defined and written out, but the second definition makes it easier to compute the product: (p_r, p_v) (q_r, q_v) = (p_r q_r - p_v ⋅ q_v, p_r q_v + q_r p_v + p_v × q_v). So far this is a simple hierarchy. But the set of scalars and the set of vectors can be embedded in the set of quaternions: R → H, a ↦ (a, 0) and V → H, v ↦ (0, v) We can also define things like the "quaternion cross product" and "quaternion dot product" for quaternions where the scalar part is zero: (0, p) × (0, q) := (p, p × q) (0, p) ⋅ (0, q) := (p ⋅ q, 0) I'm starting to think this is becoming a pointless exercise. Maybe I should just limit myself to "dual quaternions are a pair of quaternions" and "quaternions are pairs of a scalar and a vector" and forget about the magic subtyping. On Tuesday, February 6, 2018 at 12:01:42 AM UTC+1, Sam Tobin-Hochstadt wrote: > > I'm not sure how the "If" got there. > > But to say more, consider your function: > > (: 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)])) > > Now you imagine instantiating `N` with things like `(Vector3 Real)`, > but if we instantiated it instead with `(Dual-Number String)`, then > you'd have a problem. > > 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.
Re: [racket-users] Defining algebraic data types?
I'm not sure how the "If" got there. But to say more, consider your function: (: 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)])) Now you imagine instantiating `N` with things like `(Vector3 Real)`, but if we instantiated it instead with `(Dual-Number String)`, then you'd have a problem. Sam On Mon, Feb 5, 2018 at 5:50 PM, HiPhish wrote: > Did your email get cut off? > > On Monday, February 5, 2018 at 6:00:05 PM UTC+1, Sam Tobin-Hochstadt wrote: >> >> 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 > > -- > 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.
Re: [racket-users] Defining algebraic data types?
Did your email get cut off? On Monday, February 5, 2018 at 6:00:05 PM UTC+1, Sam Tobin-Hochstadt wrote: > > 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 > -- 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.
Re: [racket-users] Defining algebraic data types?
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" 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.
Re: [racket-users] Defining algebraic data types?
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.
Re: [racket-users] Defining algebraic data types?
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 On Sun, Feb 4, 2018 at 9:16 AM, HiPhish wrote: > Hell Racketeers, > > I am trying to write an implementation of the mathematical concept of dual > quaternions in Racket. Dual quaternions are an algebraic type and there are > several equally valid way to look at them. > > Let me give some background first. A dual number (a + bε) is similar to a > complex number (a + bi), except that the square of ε is 0 instead of -1. A > quaternion (a + bi + cj + dk) is like a complex number, except that it has > three complex units which all square to -1. A dual quaternion is either a > dual > number where both components are quaternions, or a quaternion where all four > components are dual numbers. There are also "subtypes" of dual quaternoins: > a > dual scalar is a dual quaternions where the vector parts of the two > quaternions > are zero, and a dual vector (not to be confused with the dual vectors from > linear algebra) is a dual quaternions where the scalar part of both > quaternions > is zero. Unlike the subtypes in OOP these algebraic subtypes have *less* > information than their parent (kind of like a square is a rectangle defined > by > only one length instead of two). (If you want to get really down to it, dual > quaternions are elements of the Clifford algebra Cl^+(0, 3, 1).) > > So my question is: what would be the best way of defining such algebraic > types? > At first I wanted to create a struct: > > (define vector (i j k)) > (struct quaternion (scalar vector)) > (struct dual-quaternon (real dual)) > > But this limits me to a "dual number where both components are quaternions" > view of the type. It also means that each dual scalar has be a sort of > mishapped dual quaternion. > > -- > 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.
[racket-users] Defining algebraic data types?
Hell Racketeers, I am trying to write an implementation of the mathematical concept of dual quaternions in Racket. Dual quaternions are an algebraic type and there are several equally valid way to look at them. Let me give some background first. A dual number (a + bε) is similar to a complex number (a + bi), except that the square of ε is 0 instead of -1. A quaternion (a + bi + cj + dk) is like a complex number, except that it has three complex units which all square to -1. A dual quaternion is either a dual number where both components are quaternions, or a quaternion where all four components are dual numbers. There are also "subtypes" of dual quaternoins: a dual scalar is a dual quaternions where the vector parts of the two quaternions are zero, and a dual vector (not to be confused with the dual vectors from linear algebra) is a dual quaternions where the scalar part of both quaternions is zero. Unlike the subtypes in OOP these algebraic subtypes have *less* information than their parent (kind of like a square is a rectangle defined by only one length instead of two). (If you want to get really down to it, dual quaternions are elements of the Clifford algebra Cl^+(0, 3, 1).) So my question is: what would be the best way of defining such algebraic types? At first I wanted to create a struct: (define vector (i j k)) (struct quaternion (scalar vector)) (struct dual-quaternon (real dual)) But this limits me to a "dual number where both components are quaternions" view of the type. It also means that each dual scalar has be a sort of mishapped dual quaternion. -- 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.