#lang plait (define-type MList [MPair (n : Number) (tail : (Boxof MList))] [Empty]) ; make (define (mlist lst) (cond [(empty? lst) (Empty)] [else (MPair (first lst) (box (mlist (rest lst))))])) (test (mlist empty) (Empty)) (test (mlist '(1)) (MPair 1 (box (Empty)))) (test (mlist '(1 2)) (MPair 1 (box (MPair 2 (box (Empty)))))) ; take (define (take k mlst) (cond [(<= k 0) empty] [else (type-case MList mlst [(Empty) empty] [(MPair n tail-box) (cons n (take (sub1 k) (unbox tail-box)))])])) ; big (define big-mlist (mlist (build-list 50 identity))) (test (take 10 big-mlist) '(0 1 2 3 4 5 6 7 8 9)) ; set (define (set-last! lst1 lst2) (type-case MList lst1 [(MPair n t) (type-case MList (unbox t) [(Empty) (set-box! t lst2)] [else (set-last! (unbox t) lst2)])] [(Empty) (error 'empty "cannot set tail")])) (define test-lst1 (mlist '(1 2 3))) (define test-lst2 (mlist '(4 5 6))) (set-last! test-lst1 test-lst2) (test (take 6 test-lst1) '(1 2 3 4 5 6)) (test (take 3 test-lst2) '(4 5 6)) (test (take 1000 test-lst1) '(1 2 3 4 5 6)) (test/exn (set-last! (Empty) test-lst1) "cannot set tail") ; cycle (define (cycle lst) (type-case MList lst [(Empty) (Empty)] [else (begin (set-last! lst lst) lst)])) (define small-cycle (cycle (mlist '(0 1 2)))) (define big-cycle (cycle big-mlist)) (test (cycle (Empty)) (Empty)) (test (take 0 big-cycle) empty) (test (take 0 small-cycle) empty) (test (take 5 big-cycle) '(0 1 2 3 4)) (test (take 5 small-cycle) '(0 1 2 0 1)) (test (take 107 big-cycle) (build-list 107 (lambda (n) (modulo n 50))))