[plt-scheme] Re: polymorphism of primitive types

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Wed Oct 19 14:43:30 EDT 2005

On Oct 18, 2005, at 3:07 PM, Bill Wood wrote:

> On Tue, 2005-10-18 at 12:26 -0400, David Van Horn wrote:
>    . . .
>> At least one of the argument lists must be finite:
>>
>> (map + '(3 1 4 1) (circular-list 1 0)) => (4 1 5 1)
>
> Since you brought it up, I've been wondering if there is some 
> compelling
> reason to require the list arguments to HOFs like map, zip, etc. to all
> be of the same length?  The Common Lisp versions don't require it.
> There have been occasions when I found the more relaxed versions, such
> as SRFI 1 and Common Lisp's, to be *very* useful.  The relaxed versions
> also help make circular lists more useful.
>
> I asked this question (in a very relaxed fashion) on the OCaml list and
> received thundering silence for my insolence :-)

An interesting question comes up here: what is the contract for such a 
function?

Here is my partial attempt:

(module mymap mzscheme
   (require (lib "contract.ss")
            (lib "list.ss"))

   (define (mymap f . argl)
     (let loop ([argl argl])
       (cond
         [(ormap null? argl) '()]
         [(andmap pair? argl) (cons (apply f (map car argl)) (loop (map 
cdr argl)))]
         [else (error 'mymap "can't happen: out of cons cells and no 
empty list")])))

   ;; (Listof X) Nat -> Boolean
   (define (has-at-least-as-many-cons-as l min)
     (let loop ([l l][min min])
       (cond [(null? l) #t]
             [else (and (pair? l) (loop (cdr l) (- min 1)))])))

   ;; (Listof X) -> Boolean
   (define (pre-mymap argl)
     (define proper-lists (filter list? argl))
     (and (pair? proper-lists)
          (andmap (let ([length-of-shortest-proper-list (apply min (map 
length proper-lists))])
                    (lambda (l) (has-at-least-as-many-cons-as l 
length-of-shortest-proper-list)))
                  argl)))

   (define pre-mymap-string
     "all args have as many leading cons cells as the shortest proper 
list")

   (provide/contract
    [mymap  {(procedure?)
             (flat-named-contract pre-mymap-string pre-mymap)
             ;; MF to Robby: this doesn't check whether the procedure? 
has the
             ;; proper arity. I don't know how to formulate such a 
contract.
             . ->* .
             (list?)}]))

Now you can use it as advertised and it is contracted.

But it would blow up on this:

           (let/ec jump
             (mymap (lambda (x y) (if (= x y) (jump #f) (+ x y))) '(1 2 
. 3) '(1 . 2)))

Should it? -- Matthias



Posted on the users mailing list.