带矢量集的键入的球拍错误

时间:2014-12-02 21:20:17

标签: vector racket typing typed-racket

我试图编写一个名为rotate-right

的函数
(: rotate-right : (All (A) (Vectorof A) Integer Integer -> Void))
(rotate right v lo hi)

修改向量v,使得区间[lo..hi-1]中的元素移动到位置[lo + 1..hi]并且将索引hi处的元素移动到位置lo。例如

(rotate-right (vector 0 1 2 3 4 5 6 7 8 9))

产生

#(0 1 5 2 3 4 6 7 8 9).

我已经写了这段代码

(: rotate-right : (All (a) (Vectorof a) Integer Integer -> Void))
(define (rotate-right v lo hi)
  (local
    {(define tmp v)
     (: vector-scan : (All (a) (Vectorof a) Integer Integer Integer -> Void))
     (define (vector-scan v lo hi c)
       (cond
         [(= c -1) (vector-set! v 0 (vector-ref v 0))]
         [(and (< lo c) (>= hi c))
          (vector-scan
           (vector-set! v c (vector-ref tmp (- c 1)))
           lo hi (- c 1))]
         [(= c lo)
          (vector-scan
           (vector-set! v lo (vector-ref tmp hi))
           lo hi (- c 1))]
         [else
          (vector-scan
           (vector-set! v c (vector-ref v c))
           lo hi (- c 1))]))}
    (vector-scan v lo hi (vector-length v))))

然而,这给了我vector-set!的类型错误。谁能告诉我我做错了什么?感谢。

2 个答案:

答案 0 :(得分:1)

我无法帮助您使用键入的部分,但您的算法也无法在常规的Racket中使用。写一个更简洁的方法(同时保持使用索引)将是:

(define (rotate-right v lo hi)
  (for/vector ((i (in-range (vector-length v))))
    (vector-ref v
                (cond
                  ((< i lo) i)
                  ((= i lo) hi)
                  ((<= i hi) (sub1 i))
                  (else i)))))

然后

> (rotate-right (vector 0 1 2 3 4 5 6 7 8 9) 2 5)
'#(0 1 5 2 3 4 6 7 8 9)

答案 1 :(得分:1)

以下是for的版本。

#lang typed/racket

(: rotate-right : (All (A) (Vectorof A) Integer Integer -> Void))
(define (rotate-right v lo hi)
  (define hi-1 (- hi 1))
  (cond
    [(>= lo hi-1) (void)]
    [else         (define tmp (vector-ref v hi-1))
                  (for ([i (in-range hi-1 lo -1)])
                    (vector-set! v i (vector-ref v (- i 1))))
                  (vector-set! v lo tmp)]))

(define v (vector 0 1 2 3 4 5 6 7 8 9))
(rotate-right v 3 7)
v

输出结果为:

'#(0 1 2 6 3 4 5 7 8 9)

问题是我们如何修复原始程序。 矢量集!返回void,我们需要分开调用 到vector-set!vector-scan

此外,矢量扫描的类型应该重用类型变量a 来自旋转a。

这给出了以下具有正确类型的程序。 (我还没有测试它是否正确旋转)。

(: rotate-right : (All (a) (Vectorof a) Integer Integer -> Void))
(define (rotate-right v lo hi)
  (local
    {(define tmp v)
     (: vector-scan : (Vectorof a) Integer Integer Integer -> Void)
     (define (vector-scan v lo hi c)
       (cond
         [(= c -1) (vector-set! v 0 (vector-ref v 0))]
         [(and (< lo c) (>= hi c))
          (vector-set! v c (vector-ref tmp (- c 1)))
          (vector-scan v lo hi (- c 1))]
         [(= c lo)
          (vector-set! v lo (vector-ref tmp hi))
          (vector-scan v lo hi (- c 1))]
         [else
          (vector-set! v c (vector-ref v c))
          (vector-scan v lo hi (- c 1))]))}
    (vector-scan v lo hi (vector-length v))))