The easiest and proper fix is to write typed macros for typed modules. Below is
a naive but straightforward solution. It would be better if define-memoized
fished out the type declaration for f and used it to add domain types for
arg-s...
#lang typed/racket
(require (for-syntax syntax/parse))
(: memoize (All (r a ...)
(-> (-> a ... a r)
(-> a ... a r))))
(define (memoize fn)
(let ([store : (HashTable Any r) (make-hash)])
(define (memfn . [args : a ... a])
(hash-ref store args
(lambda ()
(let ([result : r (apply fn args)])
(hash-set! store args result)
result))))
memfn))
(: fibo (-> Integer Integer))
(define fibo (memoize (lambda ([n : Integer])
(if (<= n 1)
1
(+ (fibo (- n 1))
(fibo (- n 2)))))))
(define-syntax (define-memoized stx)
(syntax-parse stx ;; I didn’t get the ‘:’ syntax right the first time, so I
gave up on that
[(_ (fn-name:id {arg t} ...) Tresult body ...)
#'(begin
(: fn-name (-> t ... Tresult))
(define fn-name (memoize (lambda ({arg : t} ...) body ...))))]))
(define-memoized (fib {n Integer}) Integer
(if (<= n 1)
1
(+ (fib (- n 1))
(fib (- n 2)))))
(fib 10)
> On Sep 5, 2016, at 3:11 AM, Sourav Datta <[email protected]> wrote:
>
> Another day, another typed racket question!
>
> I was experimenting with memoize library in Racket and noticed that it does
> not always work with typed racket functions (or, may be I was not
> 'require'ing it properly). So I came up with this crude implementation below
> and it seems to be working for one or more arguments:
>
> #lang typed/racket
>
> (: memoize (All (r a ...)
> (-> (-> a ... a r)
> (-> a ... a r))))
> (define (memoize fn)
> (let ([store : (HashTable Any r) (make-hash)])
> (define (memfn . [args : a ... a])
> (hash-ref store args
> (lambda ()
> (let ([result : r (apply fn args)])
> (hash-set! store args result)
> result))))
> memfn))
>
> So the typical fibo function with this memoization function would look like:
>
> (: fibo (-> Integer Integer))
> (define fibo (memoize (lambda ([n : Integer])
> (if (<= n 1)
> 1
> (+ (fibo (- n 1))
> (fibo (- n 2)))))))
>
> However, what I wanted is to define a macro similar to define/memo like in
> the Racket memoize package. A first approach like below did not work:
>
> (define-syntax (define-memoized stx)
> (syntax-parse stx
> [(_ (fn-name:id arg:id ...) body ...+)
> #'(define fn-name (memoize (lambda (arg ...) body ...)))]))
>
> The error comes in (<= n 1) call where it is given Any but expecting Integer.
> The problem is that the syntax splits the function definition in a lambda
> expression and then passes to memoize function, whose result is then assigned
> to the function name. The lambda expression without type annotation assumes
> that the arguments are Any.
>
> So in this case, is there any way we could write a macro on top of the above
> memoize that can identify the types of the underlying function and annotate
> the lambda accordingly - or is there any other way this could be achieved?
>
> Thanks!
>
> --
> 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].
> 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 [email protected].
For more options, visit https://groups.google.com/d/optout.