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?