Monadically Speaking: Benjamin’s Adventures in PLT Wonderland

November 19, 2008

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

Filed under: Scheme — Benjamin L. Russell @ 8:31 pm

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?

November 18, 2008

Towers of Hanoi

Filed under: Haskell — Benjamin L. Russell @ 1:07 pm

Next, allow me to present a Haskell version of Towers of Hanoi:

-- hanoi_v1.1.hs
-- Haskell function to compute the Towers of Hanoi problem recursively
-- 
-- Usage: putStr (hanoi_shower (hanoi 1 2 3 n)), or 
--        putStr (hanoi_shower (hanoi 'a' 'b' 'c' n)), 
--        where the first three arguments of hanoi may be polymorphic types
--        (i.e., Chars, Ints, or any other suitable type), and n is the number
--        of discs to move from the source peg to the destination peg
-- 
-- Copyright(c) April 16, 2008, at 14:17, 
-- by Benjamin L. Russell
-- 
-- Update History:
-- 
-- Version 1.0.1
-- Changed program name in comments:
-- "Hanoi.hs" -> "hanoi.hs"
-- 
-- Version 1.0.2
-- Corrected copyright date: April 17 -> April 16
-- 
-- Update History:
-- 
-- Version 1.1
-- Added usage information.
-- October 17, 2008, at 14:45

hanoi :: a -> a -> a -> Int -> [(a, a)]
hanoi source using dest n
    | n == 0 = []
    | n == 1 = [(source, dest)]
    | otherwise = hanoi source dest using (n-1)
                  ++ hanoi source using dest 1
                         ++ hanoi using source dest (n-1)

hanoi_shower :: Show a => [(a, a)] -> String
hanoi_shower [] = ""
hanoi_shower ((a, b):moves) = unlines ["Move " ++ show a ++ " to "++ show b ++ "."] ++ hanoi_shower moves

To run the Haskell source code above, simply type:

putStr (hanoi_shower (hanoi 'a' 'b' 'c' 3))

You shall be rewarded with:

Move 'a' to 'c'.
Move 'a' to 'b'.
Move 'c' to 'b'.
Move 'a' to 'c'.
Move 'b' to 'a'.
Move 'b' to 'c'.
Move 'a' to 'c'.

Beautiful, isn’t it?

So much for now.  Until next time….

What is the taste of curried Haskell?

Towers of Hanoi

Filed under: Scheme — Benjamin L. Russell @ 12:42 pm

Ladies and Gentlemen!  Welcome to DekuDekuplex’s Blog, the Never Never Land of amateur functional programming theory!

What is the value of a process that doesn’t terminate?

Allow me to present my introductory Scheme procedure, Towers of Hanoi:

;; Towers of Hanoi, plt1.1
;; PLT-Scheme-specific Version 1.1 of Towers of Hanoi
;; 
;; Copyright(C) April 02, 2008, at 19:38, 
;; by Benjamin L. Russell

(define (hanoi n)
  (hanoi-helper 'A 'B 'C n))

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

To run the Scheme source code above, simply type:

(hanoi 3)

You shall be rewarded with:

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.

Wonderful, isn’t it?

So much for now.  Until next time….

(lambda x.(x x))(lambda x.(x x))

Blog at WordPress.com.