From www@deja.com Wed Nov 29 19:44:45 2000 Message-ID: <904iqv$6cd$1@nnrp1.deja.com> From: oleg-at-pobox.com Subject: Re: ML as Scheme: Dynamic typing in a strongly-typed language Date: Thu, 30 Nov 2000 03:50:57 GMT Newsgroups: comp.lang.scheme,comp.lang.functional References: <9020t8$3kq$1@nnrp1.deja.com> X-Article-Creation-Date: Thu Nov 30 03:50:57 2000 GMT Status: OR In Scheme, evaluating (* 1 "two") causes a run-time error [1]. Given the "ML-as-Scheme-impersonator" introduced in the previous article, application s_mul [Int 1; Str "one"] causes an exception -- and eventually a _run-time_ error. In both systems inappropriate arguments and operations are detected at run-time. As far as types are concerned, the Scheme impersonator behaves _exactly_ like Scheme -- and that was exactly the point of the exercise. As Harper's thesis says, a strongly-typed system can emulate a dynamically-typed system, with all its advantages and disadvantages. The previous article made no claim that the Scheme impersonator makes somehow a better Scheme. It makes somewhat uglier Scheme, to be precise. If a programmer decided that a dynamic typing system is best for his project, he definitely should use a language which was specifically designed with latent typing in mind. Such a language will be able to offer the programmer syntactic sugar and other coding niceties that an impersonator may lack. However superficial, coding shortcuts and conveniences make programming far more enjoyable. The previous article was in response to a sentiment that sometimes static typing fits well, sometimes dynamic typing has an advantage. Some parts of a project can be implemented using a strongly-typed discipline, some parts could benefit from dynamic typing. In that case, the approach illustrated by the Scheme-ML impersonator may be of interest. You can implement a function foo as let foo [x] = baz [ bar [x] ];; In this case, foo will check, at _run-time_, that it was invoked with one parameter. bar will verify, at run time, that it receives one parameter of a desirable type. baz will decide, again at run-time, if it likes the result produced by 'bar'. You can (re-)implement the above function in a different way: let foo [x] = match x with (Int n) -> Int (baz (bar n)) | ... Function foo remains dynamically-typed. However, it is the compiler that will check, at compile time, that function bar can be used with an integer argument. The compiler will check that bar's result is suitable for baz. The latter function must return an integer result -- which will be checked at compile-time as well. Thus a programmer gains freedom to implement different parts of his project using different typing disciplines. That was the point of the previous article: _IF_ you happen to appreciate both the strong and the dynamic typing for their strengths; IF you think that your project will benefit from the mixed approach, then you may find a language like ML beneficial [2]. It will let you, the programmer, control the proportion of static and dynamic typing in the mix. Strong vs. latent typing does not have to be an XOR question. [1] Causing an error is to be distinguished from reporting an error. Once a Scheme system detects an error, it is free then to do _anything_ it wishes to, including returning 42 and looping forever. The same can be said about OCaml: a raised exception does not have to lead to any visible calamity, provided a suitable handler is installed. [2] OTH, you may find a soft-type system like Rice PLT's MrSpidey more suitable. Such a system adds static type annotations -- constraints in general -- to a dynamically typed language. A compiler may be able to check these constraints statically, by analyzing the control and data flow. The compiler may fail, in which case you can blame compiler's inhumane nature and run the program anyway. You may take a notice of a constraint under contention and attempt to prove to your own satisfaction that the constraint must, shall, should, may or might hold. Or you can choose to provide more annotations to make the compiler happier. The trouble is that not every Scheme system comes with a soft type-checker. OTH, the Scheme impersonator can run on any ML system (modulo OCaml/SML syntactic differences).