[plt-scheme] Re: type signature for a multi-parameter function of a fixed number of arguments in Typed Scheme?

From: Benjamin L.Russell (DekuDekuplex at Yahoo.com)
Date: Thu Oct 16 07:50:28 EDT 2008

On Thu, 16 Oct 2008 06:31:48 -0400, "Carl Eastlund"
<cce at ccs.neu.edu> wrote:

>You can write both multiple-argument and curried functions in Typed
>Scheme, but you have to remember to distinguish the two in your
>definitions and type specifications.  A multiple argument function is
>applied once to multiple arguments, and uses a type signature like (A
>B -> C).  A curried function is applied multiple times, usually to one
>argument each, and uses a type signature like (A -> (B -> C)).  Here
>is code for both that runs without error in Typed Scheme:
>
>#lang typed-scheme
>
>(: regular-plus (Number Number -> Number))
>(define (regular-plus a b)
>  (+ a b))

This works fine:

> (regular-plus 1 2)
- : Number
3

>
>(: curried-plus (Number -> (Number -> Number)))
>(define ((curried-plus a) b)
>  (+ a b))

This requires some care in use.  If I try using it in the same was as
regular-plus, it causes an error message; viz.:

> (curried-plus 1 2)
. typecheck: Too many arguments to function, expected 1, got 2 in:
(curried-plus 1 2)

However, if I treat (curried-plus 1) as a function to be applied to an
argument, say 2, then it works:

> ((curried-plus 1) 2)
- : Number
3
> 

Thank you!  That is exactly what I was seeking.

Now I can write a Typed Scheme version of Towers of Hanoi:

#lang typed-scheme

(: hanoi-typed (Number -> Void))
(define (hanoi-typed n)
  (hanoi-helper-typed 'A 'B 'C n))

(: hanoi-helper-typed (Symbol Symbol Symbol Number -> Void))
(define (hanoi-helper-typed source using destination n)
  (cond ((= n 1)
         (printf "Moving from disc ~a to ~a.\n" source destination))
        (else
         (hanoi-helper-typed source destination using (- n 1))
         (hanoi-helper-typed source using destination 1)
         (hanoi-helper-typed using source destination (- n 1)))))

> (hanoi-typed 1)
Moving from disc A to C.
> (hanoi-typed 2)
Moving from disc A to B.
Moving from disc A to C.
Moving from disc B to C.
> (hanoi-typed 3)
Moving from disc A to C.
Moving from disc A to B.
Moving from disc C to B.
Moving from disc A to C.
Moving from disc B to A.
Moving from disc B to C.
Moving from disc A to C.
> 

Now, here is a curried Typed Scheme version of Towers of Hanoi:

#lang typed-scheme

(: hanoi-curried (Number -> Void))
(define (hanoi-curried n)
  ((((hanoi-helper-curried 'A) 'B) 'C) n))

(: hanoi-helper-curried (Symbol -> (Symbol -> (Symbol -> (Number ->
Void)))))
(define ((((hanoi-helper-curried source) using) destination) n)
  (cond ((= n 1)
         (printf "Moving from disc ~a to ~a.\n" source destination))
        (else
         ((((hanoi-helper-curried source) destination) using) (- n 1))
         ((((hanoi-helper-curried source) using) destination) 1)
         ((((hanoi-helper-curried using) source) destination) (- n
1)))))

> (hanoi-curried 1)
Moving from disc A to C.
> (hanoi-curried 2)
Moving from disc A to B.
Moving from disc A to C.
Moving from disc B to C.
> (hanoi-curried 3)
Moving from disc A to C.
Moving from disc A to B.
Moving from disc C to B.
Moving from disc A to C.
Moving from disc B to A.
Moving from disc B to C.
Moving from disc A to C.
> 

This is fun!  If only curried-rice were so easy as curried-hanoi ;-).

-- Benjamin L. Russell

>On Thu, Oct 16, 2008 at 6:11 AM, Benjamin L. Russell
><DekuDekuplex at yahoo.com> wrote:
>> This time, I would like to write a type signature for a
>> multi-parameter function of a fixed number of arguments in Typed
>> Scheme, but the documentation ("Typed Scheme: Scheme with Static
>> Types" at http://docs.plt-scheme.org/typed-scheme/) is not clear on
>> this.
>>
>> I know how to write a type signature for a function of one argument;
>> e.g.:
>>
>> #lang typed-scheme
>>
>> (: fac (Number -> Number))
>> (define (fac n)
>>  (if (= n 0)
>>      1
>>      (* n (fac (- n 1)))))
>>
>>> (fac 5)
>> - : Number
>> 120
>>>
>>
>> I also know how to write a type signature for a function of zero
>> arguments; e.g.:
>>
>> #lang typed-scheme
>>
>> (: hello-world-function (-> Void))
>> (define (hello-world-function)
>>  (display "Hello, world!\n"))
>>
>>> (hello-world-function)
>> Hello, world!
>>>
>>
>> Additionally, I know how to write a type signature for a function of a
>> variable number of arguments:
>>
>> #lang typed-scheme
>>
>> (: my-plus-variable (Number * -> Number))
>> (define (my-plus-variable . ns)
>>  (if (null? ns)
>>      0
>>      (+ (car ns) (apply my-plus-variable (cdr ns)))))
>>
>>> (my-plus-variable)
>> - : Number
>> 0
>>> (my-plus-variable 1 2)
>> - : Number
>> 3
>>> (my-plus-variable 1 2 3)
>> - : Number
>> 6
>>>
>>
>> However, I don't know how to write a type signature for a function of
>> a fixed number n of arguments, where n > 1.  Here are my attempts to
>> write a function, my-plus, which takes exactly two arguments n1 and
>> n2, and returns their sum:
>>
>> #lang typed-scheme
>>
>> (: my-plus Number -> Number -> Number)
>> (define (my-plus n1 n2)
>>  (+ n1 n2))
>>
>> . <unsaved editor>:3:0: type declaration: too many arguments in: (:
>> my-plus Number -> Number -> Number)
>>
>> Here's another attempt:
>>
>> #lang typed-scheme
>>
>> (: my-plus (Number -> (Number -> Number)))
>> (define (my-plus n1 n2)
>>  (+ n1 n2))
>>
>> . <unsaved editor>:4:0: typecheck: Expected function with 1 argument,
>> but got function with 2 arguments in: (define (my-plus n1 n2) (+ n1
>> n2))
>> .
>>
>> I want to pass my-plus two separate arguments of type Number, n1 and
>> n2, and return their sum.  This is how my function is written in
>> regular #lang scheme:
>>
>> #lang scheme
>>
>> (define (my-plus n1 n2)
>>  (+ n1 n2))
>>
>>> (my-plus 1 2)
>> 3
>>>
>>
>> Can somebody please explain how I can write this function in Typed
>> Scheme?
>>
>> Also, does Typed Scheme support currying (from the results that I have
>> seen so far, apparently it doesn't)?
>>
>> -- Benjamin L. Russell



Posted on the users mailing list.