I'm wondering what is the best way to translate Haskell-like datatypes to Scheme. My current plan is to represent constructors with vectors, with the first element being a label representing the variant. So, for example, the following Haskell program:
data Bits = O Bits | I Bits | E deriving Show
data Nat = S Nat | Z deriving Show
inc (O pred) = I pred
inc (I pred) = O (inc pred)
inc E = E
dup (S pred) = let (x,y) = dup pred in (S x, S y)
dup Z = (Z, Z)
bus Z bs = inc bs
bus (S pred) bs = let (x,y) = (pred,pred) in (bus pred (bus pred bs))
o32 = (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O E))))))))))))))))))))))))))))))))
n26 = (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S Z))))))))))))))))))))))))))
main = print (bus n26 o32)
Would be translated as:
(define (O pred) (vector 'O pred))
(define (I pred) (vector 'I pred))
(define E (vector 'E))
(define (S pred) (vector 'S pred))
(define Z (vector 'Z))
(define (Inc bits) (case (vector-ref bits 0) ('O (I (vector-ref bits 1))) ('I (O (Inc (vector-ref bits 1)))) ('E E)))
(define (Dup val) (case (vector-ref val 0) ('S (let ((xy (Dup (vector-ref val 1)))) (cons (S (car xy)) (S (cdr xy))))) ('Z (cons Z Z))))
(define (Bus n bs) (case (vector-ref n 0) ('Z (Inc bs)) ('S (let ((xy (Dup (vector-ref n 1)))) (Bus (car xy) (Bus (cdr xy) bs))))))
(define O32 (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O (O E)))))))))))))))))))))))))))))))))
(define N26 (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S Z)))))))))))))))))))))))))))
(display (Bus N26 O32))
To my surprise, this actually performs quite well (Scheme is faster than Haskell here). But I wonder if this is the best way to do it? Is this reasonable, or is there some more "idiomatic" translation, which would be expected to perform better?