I'd suggest just going with the structs and making them transparent. It's 
only three structs and only with a handful of fields, abstracting over them 
with map and fold doesn't seem worth the added complexity IMO. But if you'd 
really like to map and fold over structs, I highly recommend using macros, 
`syntax-parse` and the struct-id 
<https://docs.racket-lang.org/syntax-classes/index.html?q=struct-id#%28form._%28%28lib._syntax%2Fparse%2Fclass%2Fstruct-id..rkt%29._struct-id%29%29>
 
syntax class to do so:

(require (for-syntax syntax/parse/class/struct-id)
         syntax/parse/define)

(define-simple-macro (struct-map type:struct-id instance-expr:expr 
map-function-expr:expr)
  (let ([map-function map-function-expr]
        [instance instance-expr])
    (type.constructor-id (map-function (type.accessor-id instance)) ...)))

(struct point (x y z) #:transparent)

;; Outputs (point 2 3 4)
(struct-map point (point 1 2 3) add1)
On Sunday, January 31, 2021 at 4:20:03 PM UTC-8 making-a-racket wrote:

> Hello. I have a project where I am needing to represent vectors (in the 
> mathematical sense), points, and colors. Both the vectors and points will 
> be 3D. I'm having trouble knowing what's an idiomatic way to represent and 
> interact with data types that are similar but different.
>
> In general, I could simply all represent them with a list or vector (in 
> the Racket sense). So I could have:
>
> (define (vector i j k) #(i j k))
> (define (point x y z) #(x y z))
>
> Then I could readily use the existing vector functions, such as vector-map 
> without having to define my own. But I don't super like this because I have 
> to define my own accessor functions like vector-i and point-y and also 
> don't get predicates like vector? for free.
>
> Another way is that I could use structs, but then I'm stuck implementing 
> things myself and across the structs. To avoid the latter point, I could 
> use pattern matching. So something like:
>
> (struct vector (i j k))
> (struct point (x y z))
>
> (define (tuple-map proc tuple)
>   (match tuple
>     [(struct vector (i j k)) (vector (proc (vector-i tuple))
>                                      (proc (vector-j tuple))
>                                      (proc (vector-k tuple)))]
>     [(struct point (x y z)) (point (proc (point-x tuple))
>                                    (proc (point-y tuple))
>                                    (proc (point-z tuple)))]
>     [(struct color (r g b)) (color (proc (color-r tuple))
>                                    (proc (color-g tuple))
>                                    (proc (color-b tuple)))]))
>
> But of course, this map doesn't take multiple tuples. And this feels 
> awkward, because I'll need to implement other things, like fold. Map and 
> fold would be used in defining new operators on vectors and points, like 
> addition, normalization (for vectors only), etc.
>
> The ideal thing would be that I could define a struct for these types, 
> that had the accessor functions like vector-i and predicates likes vector? 
> but was actually represented by a vector (in the Racket sense) underneath 
> the hood. Does something like this exist in Racket (not classes please).
>
> In F#, I did this same thing using F#'s records for the vector, point, and 
> color data types, and they inherited an ITuple interface (F#'s immutable, 
> functional data types can implement interfaces). Can Racket's stucts 
> inherit from interfaces? Is there something I can do with generics?
>
> Thanks for any help on this design.
>

-- 
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].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/a0220f5d-e278-454a-bc57-b7686551e486n%40googlegroups.com.

Reply via email to