Dynamic types in Clean (it's short, frode),

Nick Kallen phantom@earthlink.net
Fri, 7 Nov 1997 15:12:25 -0800


Frode, I'm forwarding to you an exerpt from some email I got off the Clean
mailing list. I find it terribly fascinating, and I think you will to. There
are some syntax issues that might confuse you, so I'll just summarize:

# precedes a block of let statements.
E.g., this allows an functional-imperitive programming style with nested
lets:
#  x = 5
    x = x + 1
    x = x / 6

The * preceding types means something's unique. Clean can't do destructive
updates without it. World represents the external world.

I dunno if dutch people spell "interpret" like "interprete" or the guy just
forgot to spell-check his code... but read away!

>> Can you give a simple example of a dynamic type in clean and a spiffy
>> function that uses it to do something otherwise impossible?
>
>Dynamic types are about to be implemented in Clean. Two constructs have
>been defined.
>One for packing a value together with its type:
>   dynamic 5 :: Int
>
>And one for unpacking the 'dynamic' object again, by doing a run-time
>pattern match on its type:
>   f :: Dynamic -> Int
>   f (x :: Int)  = x
>   f (x :: Bool) = if x 1 0
>   f  _          = 0
>
>
>The spiffy function I would like to show is is a very small command-based,
>file-based operating system, somewhat like the Unix Operating System.
>It assumes that a file consist of one object of type dynamic, and it
>is capable of applying the contents of one file (the command) to the
>contents of another (the argument), and check in a run-time type check
>that this application is type safe.
>
>
>module OpSys
>
>import StdEnv
>
>/*
>    This is a command-based, file-based operating system, somewhat like the
>    Unix Operating System.
>    The program reads a number of filenames, interpretes the first file as
a
>    command, and the next files as its arguments.
>    Think of the command and its arguments as being a compiler applied to a
>    textfile, a previewer applied to a postscript file, or even a new
Kernel,
>    replacing this one.
>*/
>
>Kernel :: *World -> *World
>Kernel world
>    # (line,world) = getCommandline world
>      world = interprete (parse line) world
>    = Kernel world
>where
>
>    interprete :: [String] *World -> *World
>    interprete [] world
>        = world
>    interprete [command:args] world
>        # (commandFile,world) = readDynamic command world
>        = addArguments commandFile args world
>    where
>
>        addArguments :: Dynamic [String] *World -> *World
>        addArguments (command :: *World -> *World) [] world
>            = command world
>        addArguments (command :: a -> b) [arg:args] world
>            # (argFile,world) = readDynamic arg world
>            = case argFile of
>                (arg :: a) = addArguments (dynamic (command arg) :: b) args
>world
>                else       = Error "argument has wrong type" world
>        addArguments _ args world
>            = Error "No such command / command has too many arguments"
world
>
>
>getCommandline :: *World -> (String,*World)
>parse :: String -> [String]
>readDynamic :: String *World -> (Dynamic,*World)
>Error :: String *World -> *World

Beautiful, eh?