| Related sites for http://www.hprog.org/fhp/MlLanguage |
| Host_On_The_Range Offers UNIX shared hosting. Supports FrontPage extensions, PHP and Java. | | Alan_J__Munn Offering hosting and email services. | | RTG__Real_Time_Systems_Group University of Pennsylvania, Philadelphia. Goal: develop methods, tools, systems to facilitate designing and implementing reliable distributed RT systems. Current projects: developing specification and | | OCERA Open Components for Embedded Real-time Applications: integrated execution environment for embedded realtime programs. Combines 2 kernels, Linux and RTLinux-GPL to support critical tasks (RTLinux-GPL e | | FilterProxy An HTML-rewriting proxy with Web-forms based configuration and modules for XSLT, GIF deanimation, and compression. [Perl] | | Betty_and_Gordon_Moore_Library Holds Cambridge University Library's working collections in mathematics, physics, astronomy, computer science, materials science, engineering. [Cambridge University Library] | | Mozilla_i18n_&_L10n_Definitions Internationalization (a.k.a. Globalization, a.k.a. Enabling); Localization; Localizability; i18n; L10n; L12y; Locale; Resource; Core product | | A_registered_educational_trust Markaz-E-Adab-O-Science (MAS), a registered educational trust - Jharkhand | | System_Support_Products,_Inc_ Offer word processing, email, graphics, spoolfile management and workstation security software. [AS/400, S/36] | | Free_Fortran_Compilers_and_Interpreters Links to free compilers and interpreters, mostly Fortran 77. | | Paraben\'s_World_Clock Is a world time clock, an atomic clock synchronizer, a stopwatch, and a countdown timer. | | XP2006 The 7th International Conference on eXtreme Programming and Agile Processes in Software Engineering. June 17 - 22, 2006, Oulu, Finland (June 17, 2006) | | Opennap-NG Opennap NG is a further development of the well known opennap-server created by drscholl. | | osCommerce_eBooks Offers eBooks detailing how to make osCommerce site more appealing to visitors and the Search Engines. | | Online_IT_Pro Contains articles for Windows Vista and XP, Firefox and PC Maintenance. | | Spiderplus Offers graphics and web design services. | | DCC_Web_Designs Offers web design and development services. | | G__D__Technologies Offers web design, hosting, and search engine placement. | | Fitch_Advertising_and_Web_Design Firm specializing in website design, internet and email marketing, and search engine optimization. Includes services and portfolio. | | OpenDocument_Fellowship Grass roots group promoting the file format. Details of activities, online resources, and membership information. |
|
MlLanguage - The Fellowship of Hobbyist Programmers Search:LoginMlLanguageRecentChangesFindPageHelpContentsMlLanguageImmutable PageCommentsInfoAttachments More Actions: Raw TextPrint ViewRender as DocbookDelete Cache------------------------Check SpellingLike PagesLocal Site Map------------------------Rename PageDelete Page------------------------Subscribe User------------------------Remove SpamRevert to this revisionPackage PagesSync Pages------------------------LoadSave What is ML?ML stands for "meta language," though that meaning isn't very relevant to the language today. Today it is simply a family of general purpose programming languages. The two main dialects in use today are Standard ML, a mathematically defined version of the language formulated in part by some of the original language developers; and OCaml, an offshoot version from the original ML to which features are added at will without defining them in a standard. Here I'll be talking primarily about Standard ML. There are many more compilers available for it. CompilersOCamlObjective Caml (see also OcamlLanguage) Standard MLStandard ML of New Jersey, the first and most popular SML compiler MLton is the best optimizing SML compiler. Moscow ML (SML) ML Kit (SML) PolyML (SML) Web resourcesOpen Directory category Introduction to Programming in Standard ML: a thorough introduction to the language aimed at university students A Gentle Introduction to ML: notes from a university course A Gentle Introduction to ML (Original, but Dead Link): notes from a university course SmlPaste - the place to paste your SML Why You Want to Start Using SML TodayA note about syntax: Many people who read this page or otherwise learn about ML for the first time claim that the syntax is inherently bad, hard to follow, etc.. These people are universally the kind who only know languages that are effectively clones of C, and thus have nearly the same syntax as C does. They expect each "new language" they learn to essentially be C with some minor cosmetic changes, and perhaps a few new features added on. If you find yourself agreeing with them, keep in mind that if you spent even a fraction of the time accustoming yourself to SML syntax as you have with the syntax of C-like languages, you would find SML to be exceptionally easy to read and understand, even without the comments that equivalent C programs often require. The flow of control in SML is conceptualized in fundamentally different (and, in my opinion, better) ways, so you won't find a trivial mapping between C and SML code. It's type safeAn SML program that compiles can't "crash" unless something catastrophic, like running out of memory, happens. The type system of SML is designed specifically to limit allowable programs to eliminate common errors like buffer overflows, dangling pointers, and such. I guarantee you that you will save yourself a great deal of time using a strictly typed language like SML over an alternative like C (and its relatives) or Lisp, where huge classes of errors go undetected until runtime, though they could have been caught by an ML compiler. For more information on type safety and the kinds of errors it can help you avoid, see AboutTypeSafety. It's mostly functionalIn a purely functional programming language, a program is just a single expression to be evaluated. There are no "side effects" or "memory" to worry about. Programming in functional style makes code easier to write, understand, and debug. You can write almost all the code you would want to write in SML in functional style. For cases where mutable aspects are too helpful to omit or are necessary for some speed goal (i.e., hash tables), SML has references (like Java's references, they are basically pointers on which you can't do arithmetic) and arrays. It compiles to fast code with a good compilerSeasoned C hackers, after reading the above, are probably thinking that the above will necessarily lead to convoluted code that is compiled to a form with many runtime checks to guarantee this safety. However, this is anything but true! A functional language can be simpler for a compiler to analyze and optimize, and ML's type system is carefully designed to avoid any need for runtime checks, outside of things like bounds checks for arrays, a language element seldom used. Don't believe me? Check out the The Computer Language Shootout. It's a series of benchmarks of over 30 different language implementations, measuring speed, memory usage, and lines of code required. It's garbage collectedAlmost all popular languages today but C and C++ use garbage collection. It's simply not worth the programmer's time to worry about memory allocation details in application development. SML takes advantage of the availability of a garbage collector to allow you to write complicated expressions that perform several memory allocations without your needing to worry about the details. For example, to return more than 1 value from a function in C, you generally pass a pointer to an output location to which the function writes its result. In Java, you might create a separate class just to hold the particular combination of values that the function returns. In SML, all you need to do is return a tuple, a sequence of values of a particular sequence of types. When an SML compiler sees an expression like (1, "text"), it implicitly allocates heap space for an int and a string and returns its address to be used just as conveniently as if you were dealing with an int alone in the rest of your code. When this pair isn't needed anymore, the garbage collector can free its memory. All of this is done without the programmer even needing to realize there is such a thing as a heap, and he doesn't need to define a separate data structure for this one simple purpose. Because of this, the compiler can also tell that tuples created in two separate places with the same types have the same type, when in other languages, special purpose types with different names might have been created in the two places. SML also has records, which are similar to tuples but have names for each of their elements instead of numbered positions. You can use them just as easily. It has parametric polymorphismIn languages like C++ and Java, polymorphism mainly takes the form of letting you write as many different versions of the same function as you want, differentiated by the types of the parameters they take. You need to write one version of the function for every combination of parameters you want to pass. In SML, you write one version of a polymorphic function and call it with parameters of as many compatible types as you please. The simplest example is: fun f(x) = x;f(1) ===> 1f("text") ===> "text"The ===> indicates an expression evaluating to a value. The lines with ===> are not SML code. They have valid code on both sides of the arrow, and the use of the arrow indicates that the expression on the left evaluates or "simplifies" to the final value on the right. The first line above defines a polymorphic function named f. It's polymorphic because it can take a parameter of any type, since all it does is return it unchanged. You can think of such a function as taking both type parameters and value parameters. In the first function call, the type parameter is int and the value parameter is 1. In the second, the type parameter is string and the value parameter "text". A slightly more complicated example: fun incrementFirst(x, y) = (x + 1, y)incrementFirst(1, 2) ===> (2, 2)incrementFirst(1, "text") ===> (2, "text")Here, the first parameter must be an int because we add 1 to it, but the second parameter may be of any type. It has first class functions and lexical closuresIn C, you can use function pointers to pass function addresses around, for such purposes as providing "callback functions" that library functions call with certain parameters to obtain effects that you want. This is useful, but not too useful, since if you want to, for example, have the behavior of your callbacks depend on some "constants" that have different values at different points in your program, you have to either use global variables, in which case you have to be careful to only use one "version" of the callback function at a time, or rewrite the function for each set of constants. In contrast, SML and most functional languages have first class functions with closures, meaning that "function pointers" also have a set of values stored with them. You can use the same address with different sets of values just as easily as you would use a function pointer in C. A simple example is a function that takes in a value and returns a "new" function that adds that value to its parameter: fun makeAdder(n:int) = (fn x:int => x + n);val myTwoAdder = makeAdder(2);val myThreeAdder = makeAdder(3);myTwoAdder(1) ===> 3myThreeAdder(1) ===> 4Each time this function is called, it returns a closure that consists of a function pointer that always points to the same function and an int value for n that varies based on what makeAdder was passed. You can then treat this returned function as an equal of any "normal" function and call it with any int parameters you please, whereon it will return each parameter with the value of n associated with it added. While this sounds complicated, in SML all of this is made easy, as functions (or closures) are values just like int's or string's. Having first class functions also lets you do all sorts of things that are very awkward to do in imperative languages. For instance, it's trivial to compose two functions: fun compose(f, g) = (fn x => f(g(x)))This compose function takes two functions as arguments as easily as it might take two int's, and it creates a new function (closure) that is their composition. (The composition of two functions is the function that passes its parameter to one of them, and then returns the result of passing that result to the second one.) To see the usefulness of this, imagine you have written a function to parse input and return a useful data structure. You already have a function that takes the useful data structure and produces a statistic about it. You can compose the two to create a function to produce the statistic from the initial input. Someone reading your code can see that you have used the compose function and understand instantly what kind of conceptual combination of functions you have made. There are many, many kinds of popular function combinators that create new functions from old ones, but I won't go into them any more here. It supports polymorphic, recursive datatypes with pattern matchingWhile C hackers will defend the usefulness of pointers in general, we can usually divide the ways pointers are used into a few categories, none of which need the full range of operations allowed on pointers. One of these is arrays. Having a separate array type with bounds checking is the simple solution to this problem. Your program might run infinitesimally more slowly, but you won't have to worry about buffer overflow bugs at all. The other main use of pointers in C is with linked data structures, such as linked lists and trees. It's readily apparent that you certainly don't need to do any arithmetic on pointers to use these. For instance, a general linked list data structure ends up written like the following in C: typedef struct list{ struct list *next; void *value;} list;... and a function to sum the values found in a list of int's looks like something like this: int sum(list *head){ int ret = 0; for (; head; head = head->next) ret += *(int *)(head->value); return ret;}If we want to use the same list structure for all carried types, we're forced to use a void* for the carried value type. When we want to actually access the data, we need to "cross our fingers" and hope that the pointer we have to the data is (a) not null and (b) actually pointing to something of the right type. We also need to write the same sorts of loops and similar things over and over again to analyze data structures and walk through their links. In C++, you can use templates to avoid some of this, but templates work through simple text substitution, leading to bizarre error messages when you try to use one incorrectly. In Java, you can have generic container structures, but you have to "downcast" the generic Object's stored in them, incurring a runtime cost when you know all along what type objects are really found in them. In SML, you can neatly express these linked structures with datatype definitions like the following, something very similar to the standard SML list type: datatype 'a list = Nil | Node of ('a * ('a list))The above is quite simple, and expresses what a linked list is much better than the C, C++, or Java version. datatype is a language keyword for declaring new structured types. 'a is a type variable that can stand for any type. Nil and Node are arbitrary user-chosen names, while * in a type indicates a pair type whose values are pairs of values of the component types. Any linked list is one of two things: empty (Nil) or a Node with a carried value of some type ('a) followed by another list with values of the same type. That's all there is to it. No pointers involved; we only need implicit "pointers" to certain values of this same type. It's then easy to write a sum function equivalent to the one above, except that the SML compiler can check for you that you are calling this one with correctly typed parameters. fun sum (Nil) = 0 | sum (Node(value, rest)) = value + sum(rest)Here we use SML's pattern matching, a natural complement to datatypes. We can break up our function definition based on the structure of the parameter, much like a piecewise definition of a mathematical function. It's a natural way to think about how a function should work. From the patterns used, the compiler infers that this function takes in a list of some sort. From the fact that the value carried in the list is added to something with +, the compiler infers that the function takes an int list. You can, of course, use much more complicated patterns than these, involving several levels of nesting of several different datatypes. We can also write generic list handling functions that don't care about what types their parameters carry just as easily (more easily, actually) than with void*'s in C: fun length (Nil) = 0 | length (Node(_, rest)) = 1 + length restThe above function is almost identical to sum, except that it uses a "wildcard" pattern _ to indicate a part of its parameter that needs no name in the function body, and that this version finds the length of a list instead of the sum of its elements. Because the carried values aren't used in the body of length, the compiler infers that the parameter type of this function is 'a list, a list with any type of values carried. Without doing any more work than with a specific list type, we have a function that handles lists of all types. It has an excellent module systemSML has a module system centered around structures and signatures, which are analagous to Java classes and interfaces, respectively. The difference is that while a Java class introduces a single new type, the type of instances of that class, an ML structure can introduce as many new types as it wants, as well as values of those types and functions that act on those types. By having an ML structure ascribe opaquely to a signature that in effect says "this structure defines a type named fred, but I won't tell you what it actually is," you can enforce data representation abstraction in a way that is more general than "data hiding" in object oriented programming. For example, you can create a simple stack structure with the following: signature STACK =sig type 'a stack val empty : 'a stack val push : 'a * 'a stack -> 'a stack val pop : 'a stack -> 'a * 'a stackendstructure Stack :> STACK =struct type 'a stack = 'a list val empty = nil fun push (elem, stack) = elem::stack (* This adds elem to the beginning of stack *) fun pop (first::rest) = (first, rest) (* The pattern here matches something of the built-in list type and separates it into its parts *)endIn the signature definition, the text you see after :'s is types. The rich type system of ML allows you to specify the type of any structure member, including functions, in a unified way, as opposed to separate field and method definition styles in C++ or Java. While the example signature defines only one type for simplicitity, it could just as well define 0 or 100 types, specifying definitions for some and leaving some abstract. Now code that wants to use a stack can use Stack without worrying about the actual representation. From outside code, you can't even accidentally rely on the actual implementation of the stack type. In the discussion of parametric polymorphism above, I mentioned templates. Obviously C++ templates can be used to do much more than just deal with container types holding values that don't need to be touched. In SML, you can duplicate the effects of such uses of templates that are actually well-typed by using functors. A functor is basically a sort of function that can take structures as parameters and return a structure. For instance, we can design an algorithm that relies on a stack and write its code inside a functor that takes an implementation of STACK as a parameter: functor SomeAlgorithm(SomeStack : STACK) =struct (* ... code that uses SomeStack ... *)endstructure ActualCode = SomeAlgorithm(Stack)It is also possible to, for instance, take in a structure that defines a type and a function for comparing two values of that type, and return a structure that gives you binary search trees with keys of the type taken in. This requires no runtime checks like you would get with a similar generic data structure in Java that holds keys implementing an interface containing a comparison method. When I got interested in ML, the following slides gave me an idea of what ML was about and what it could do... for instance, you can detect infinite loops in sort algorithms by ML's strong type checking. Here is the URL - http://perl.plover.com/yak/typing/ In a sense, you could say this is a "ML for Perl Programmers" tutorial. -- TerrenceBrannon I don't recommend the Gentle Introduction to ML: what it says is not in line with the SML/nj interpreter at least twice. Here's one case. It says the following is acceptable: http://shack.divinecode.org/giml/st2.htm#a3_5 namely, [ord, size] but the current intepreter balks on it. Further it claims the signature of these two functions is the same but ord is char -> int and size is string -> int. -- TerrenceBrannon --- CategoryLanguage MlLanguage (last edited 2008-07-09 05:47:58 by localhost)Immutable PageCommentsInfoAttachments More Actions: Raw TextPrint ViewRender as DocbookDelete Cache------------------------Check SpellingLike PagesLocal Site Map------------------------Rename PageDelete Page------------------------Subscribe User------------------------Remove SpamRevert to this revisionPackage PagesSync Pages------------------------LoadSave MoinMoin PoweredPython PoweredGPL licensedValid HTML 4.01 |
|