Skip to content

“Good Luck!,” Typed Scheme, and Curried Typed Scheme

November 19, 2008

Word of a strange variant of PLT Scheme known as “Typed Scheme” is spreading around (see http://www.ccs.neu.edu/home/samth/typed-scheme/).  The idea is to add types to Scheme and make it more like Haskell.  Doing so is supposed to make it easier to debug procedures.

I couldn’t resist, so I decided to write up a sample Typed Scheme procedure.  Called “good-luck.ss” in regular PLT Scheme, it changes the output message depending on the input user name:

;; good-luck.ss
;; PLT-Scheme-specific program to wish a person good luck
;; 
;; Copyright(C) October 20, 2008, at 13:42, 
;; by Benjamin L. Russell

#lang scheme

(define (good-luck name)
  (if (string=? name "Nobody")
      (printf "You are ~a." name)
      (good-luck-helper name "Good Luck")))

(define (good-luck-helper a b)
  (printf "~a, ~a!" a b))

To run the Scheme source code above, simply type:

(good-luck "Benjamin")

You shall be rewarded with:

Benjamin, Good Luck!

Alternatively, typing

(good-luck "Nobody")

will result in:

You are Nobody.

Well, by itself, this isn’t any fun, so I then decided to translate this into a Typed Scheme procedure named “good-luck-typed.ss”:

;; good-luck-typed.ss
;; Typed Scheme version of good-luck.ss program to wish a person good luck
;; 
;; Copyright(C) October 20, 2008, at 13:46, 
;; by Benjamin L. Russell

#lang typed-scheme

(: good-luck-typed (String -> Void))
(define (good-luck-typed name)
  (if (string=? name "Nobody")
      (printf "You are ~a." name)
      (good-luck-helper-typed name "Good Luck")))

(: good-luck-helper-typed (String String -> Void))
(define (good-luck-helper-typed a b)
  (printf "~a, ~a!" a b))

Let’s see … the main changes are the places where “#lang typed-scheme” has been added, and where “(: good-luck-typed (String -> Void))” and “(: good-luck-helper-typed (String String -> Void))” have been inserted.

Let’s take a look at this piece of code.  The procedure “good-luck-typed” takes a parameter of type String, and returns nothing (i.e., it returns a value of type “Void”).  The procedure “good-luck-helper-typed” takes two parameters of type String, and also returns nothing (i.e., it also returns a value of type “Void”).

Let’s see what happens:

> (good-luck-typed "Benjamin")
Benjamin, Good Luck!
> (good-luck-typed "Nobody")
You are Nobody.
>

Yes, the results are identical.

Normally, I would start writing about the differences when errors arise, but I don’t have time today, so let’s do that next time.

Lastly, I became curious about whether currying (see http://en.wikipedia.org/wiki/Currying) was possible.  Let’s give it a try:

;; good-luck-curried.ss
;; Curried Typed Scheme version of good-luck.ss program to wish a person good luck
;; 
;; Copyright(C) October 20, 2008, at 17:44, 
;; by Benjamin L. Russell

#lang typed-scheme

(: good-luck-curried (String -> Void))
(define (good-luck-curried name)
  (if (string=? name "Nobody")
      (printf "You are ~a." name)
      ((good-luck-helper-curried name) "Good Luck")))

(: good-luck-helper-curried (String -> (String -> Void)))
(define ((good-luck-helper-curried a) b)
  (printf "~a, ~a!" a b))

Hmm … the main differences are the “(: good-luck-helper-curried (String -> (String -> Void)))” and “(define ((good-luck-helper-curried a) b).”  Indeed, our gourmet code looks curried.  ;-)  Still, I can’t help wondering why in “(: good-luck-helper-curried (String -> (String -> Void))),” the parentheses are folded to the right, while in “(define ((good-luck-helper-curried a) b),” they are folded to the left….

Moving on (there is no time left, so let’s worry about that next time), let’s see what happens:

> (good-luck-curried "Benjamin")
Benjamin, Good Luck!
> (good-luck-curried "Nobody")
You are Nobody.
>

Right, identical results again.

Let’s worry about the details next time.

How hot would you like your curried Typed Scheme?

Advertisements
2 Comments
  1. slobodan blazeski permalink

    If you’re interested in statically typed languages you might have a look at Qi http://www.lambdassociates.org/
    Anyway I’m working on my own programming language edi, that will be close cousin to Scheme, and I’m thinking of adding type system with optional type checking. But for now I’m not convinced that type system is worth the hassle.

  2. Benjamin L. Russell permalink

    Sorry for the late response; I had been off on a special assignment for a week, and needed time to catch up with my work upon returning.

    Actually, I’ve already downloaded and installed Qi II (on GNU CLISP 2.45), and followed part of the “Qi for the ML Programmer” tutorial (see http://www.lambdassociates.org/qiml.htm). The reason that I haven’t posted a blog entry on it is that I had been trying to learn enough of it to write a version of Towers of Hanoi, properly commented, in it to post, but with my special assignment, just didn’t have enough time.

    Qi seems to be a fascinating language. Although it is built on top of Common Lisp, it actually seems to be more of a hybrid of Scheme and Haskell. What is intriguing about Qi is that the language is just semantically similar enough to Haskell to achieve a symbiotic pedagogical relation for the student; i.e., learning Qi helps to elucidate Haskell concepts, and vice-versa.

    Another language that I just discovered two days ago, and am currently experimenting with, is Refal, an abbreviation for “Recursive Functions Algorithmic Language” (see http://www.refal.net/index_e.htm). Refal was designed by Valentin Turchin (see http://pespmc1.vub.ac.be/TURCHIN.html), a Russian emigrant, currently Professor Emeritus of Computer Sciences at the City College at the City University of New York. Refal is a functional programming language with pattern matching oriented toward symbol manipulation, wherein the pattern matching works forwards, unlike in Prolog, wherein it works backwards.

    An example of a simple Refal function to determine whether a given string is a palindrome is as follows:

    Pal { = True;
         s.1 = True;
         s.1 e.2 s.1 = <Pal e.2>;
         e.1 = False; }

    The above-mentioned code defines a function Pal, which executes a sequence of pattern-matching statements. Basically, it reads as follows (where s.1 is a free variable matching any symbol consisting of a single character, e.2 is a free variable matching any expression, and the angle-brackets “<>” are used to delimit a function call within):

         If a string is blank, then return True;
         else if the string consists of only one character, then return True;
         else if the string consists of only one character, followed by any expression, followed by the same one character, then call Pal recursively on the expression;
         else if the string consists of any other expression, then return False.

    Elegant, don’t you think? One aspect of Pal that I really like is the fact that it is based on symbol manipulation, rather than numerical computation. One of my dreams is one day to design a functional program that can pass the Turing Test, and for that, symbol manipulation seems more relevant than numerical computation.

    A version of Refal-5 for win-32 is bundled with SciTE in a package called “Refal-SciTE,” downloadable in a self-installing installer at the Web site “Integrated cover for program developing” (http://www.refal.net/~belous/refsci-e.htm) (the download page, linked to from that page, is http://www.refal.net/~belous/download-refalscite.htm).

    I’ll write about both Qi II and Refal-5 as soon as I find time. Thanks for commenting!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: