Following code works perfect:
#lang typed/racket
(require racket/match )
(define-struct myoperand ([ O : [U 'plus 'minus] ]))
(define-struct myleaf ([ L : Number]))
(define-struct mynode ([ N :(cons myoperand (cons ExpT ExpT))]))
(define-type ExpT (U myleaf mynode))
(: myeval : ExpT -> Number)
(define myeval
(lambda (x)
[match x
([myleaf L]
L
);case
([mynode N]
(if (equal? (myoperand-O (car N)) 'plus)
(+
(myeval (car (cdr N)))
(myeval (cdr (cdr N)))
);+
-1;else
);if
);case
];match
);lambda
);define
(define testleaf1 (make-myleaf 1))
(define testleaf2 (make-myleaf 2))
(define twoleafs (cons testleaf1 testleaf2))
(define testoperand (make-myoperand 'plus))
(define testnode (make-mynode (cons testoperand twoleafs)))
(define testnode2 (make-mynode (cons testoperand (cons testnode testnode))))
(write (myeval testleaf1))
(write (myeval testnode))
(write (myeval testnode2))
(write (myeval testnode3))
Then i modified to code to use more "symbols" as it is a uniform representation of data.
#lang typed/racket
(require racket/match )
(define-type myoperand Symbol)
(define-struct myleaf ([ L : Symbol]) #:transparent)
(define-struct mynode ([ N : (cons myoperand (cons ExpT ExpT))]) #:transparent)
(define-type ExpT (U myleaf mynode))
(: myeval : ExpT -> Number)
(define myeval
(lambda (x)
[match x
[(mynode N)
(if (equal? (car N) 'plus)
(let* ([x (cdr N)]
[y (car x)]
[z (cdr x)])
(+ (myeval y) (myeval z))
);let
-1;snd
);if
];1st-match
[(myleaf L)
(begin
(let* ([astr (symbol->string L) ]
[n (string->number astr)])
(if n n -1)
);let
);begin
] ;2nd-match
];match
);lambda
);define
(define testleaf1 (make-myleaf '|1|))
(define testleaf2 (make-myleaf '|2|))
(define twoleafs (cons testleaf1 testleaf2))
(define testoperand 'plus)
(define testnode (make-mynode (cons testoperand twoleafs)))
(write (myeval testleaf1))
(write (myeval testnode))
One of the errors:
Type Checker: Polymorphic function `car' could not be applied to arguments:
Types: (Pairof a b) -> (a : ((! (car (0 0)) False) | (: (car (0 0)) False)) : (car (0 0)))
(Listof a) -> a
A few hints, but I still couldn't make the program typecheck:
-
'1
is the number 1
. To get the symbol whose string representation is "1"
you must write '|1|.
-
The result of string->number
may be #f#
, so TR complains that it may not be a number. You can use for example (or (string->number astr) +nan.f)
so the result is always a number.
-
My guess is that [ N : (Listof Symbol)]
should be [ N : (List Symbol Symbol)]
so TR is sure that it can apply (car (cdr ...))
, but I'm not sure.
1 Like
There are a lot of possible ways of fixing this, but let me ask one or two questions first.
-
You gave the N
field of myNode the type (Listof Symbol)
. That's not a useful choice, because it means that you can't put nodes inside of nodes. I'm ... assuming that you wanted to be able to nest nodes inside nodes?
-
I'm not sure why you want to use more symbols as a more uniform representation of data, or what exactly you mean by that. I can see two directions you can go in: First, you could make all of your inputs s-expressions, leveraging racket lists. Second, you could go for pure structs, and use symbols and lists only where they're natural choices (e.g. using a list for an arbitrary-length collection of arguments). Which of these are you heading toward? If you don't have a strong opinion, I would steer you toward the second one; it's certainly closer to OCaml, and gives you better type checking, and simplifies the type-checking in and around operators like 'car' and 'cdr'.
-
In case you're not already familiar with this, adding the #:transparent
tag to structure definitions makes them print more usefully, and allows them to be compared by the testing framework. I strongly suggest using this tag on every structure definition. E.G.:
(define-struct myleaf ([ L : Number]) #:transparent)
(Also, you can just use struct
rather than define-struct
.)
2 Likes
I cleaned the code:
#lang typed/racket
(require racket/match )
(define-struct myoperand ([ O : [U 'plus 'minus] ]) #:transparent )
(define-struct myleaf ([ L : Number]) #:transparent )
(define-struct mynode ([ OP : myoperand ] [ E1 : myexpr ] [ E2 : myexpr ] ) #:transparent )
(define-struct myexpr ([ E : (U myleaf mynode)]) #:transparent )
(: myeval : myexpr -> Number)
(define myeval
(lambda (x)
[match (myexpr-E x)
([myleaf L] L );case
([mynode OP E1 E2]
(if (eq? (myoperand-O OP) 'plus )
(+ (myeval E1) (myeval E2) );+
-1000;else
))]))
(: to_expra : Number -> myexpr )
(define to_expra
(lambda (x)
[let* ([l (make-myleaf x)]
[e (make-myexpr l)]
);let
e
];let
);lambda
);define
(: to_exprb : ( U 'minus 'plus ) Number Number -> myexpr )
(define to_exprb
(lambda (x1 x2 x3)
[let* ([op (make-myoperand x1)]
[l1 (make-myleaf x2)]
[l2 (make-myleaf x3)]
[n (make-mynode op (make-myexpr l1) (make-myexpr l2))]
[e (make-myexpr n)]
);let
e
];let
);lambda
);define
(: to_exprc : ( U 'minus 'plus ) myexpr myexpr -> myexpr )
(define to_exprc
(lambda (x1 e1 e2)
[let* ([op (make-myoperand x1)]
[n (make-mynode op e1 e2)]
[e (make-myexpr n)]
);let
e
];let
);lambda
);define
(write (myeval (to_expra 1)))
(write (myeval (to_exprb 'plus 2 3)))
(write (myeval (to_exprc 'plus (to_exprb 'plus 4 5) (to_exprb 'plus 6 7))))