ML語言

ML語言

ML語言
ML語言是通用的函數式編程語言,由愛丁堡大學的Robin Milner及他人在二十世紀七十年代末開發的。其語法是從ISWIM得到的靈感,作為元語言的ML是為了幫助在LCF定理證明機中尋找證明策略而構想出來的。
  • 性質:通用的函數式編程語言

ML語言簡介

ML 是一個通用的函數式編程語言,它是由愛丁堡大學的Robin Milner及他人在二十世紀七十年代晚期開發的。它的語法是從ISWIM得到的靈感。作為元語言的ML是為了幫助在LCF定理證明機中尋找證明策略而構想出來的。(之前的元語言是pplambda,它聯合了一階邏輯演算、多态及Λ演算)。它使用了Hindley-Milner類型推論算法來推測大多數值的類型,而不需要四處使用注解。

ML一般被歸為非純函數式編程語言,因為它允許副作用和指令式編程。這一點和純函數是編程語言??例如Haskell??很不一樣。

ML特性有惰性求值的求值策略,一階類型函數,帶有垃圾收集的自動内存管理參數多态,靜态數據類型,類型推斷,代數數據類型,模式匹配和異常處理。

不像Haskell,ML使用熱情求值,也就是說所有的子表達式總是被求值。導緻的一個結果是你不能使用無窮表。然而,惰性求值産生的無窮表可以通過使用匿名函數來模拟。

今天在ML家族中有好幾種語言:兩種主要的方言是Standard ML和Caml,其他的包括F# - 針對Microsoft .NET平台的開放研究項目。 ML中的思想影響了衆多的語言,例如Haskell,Cyclone和Nemerle。   ML的實力大多被用于語言設計和操作(編譯器、分析器、定理證明機),但是它作為通用語言也被用于生化,金融系統,和宗譜數據庫,一個P2P的客戶/服務器程序等等。

ML可以算一種具備命令式語言特點的函數型語言,或者說面向函數的命令型語言。和Lisp一樣,ML具有非常靈活的函數功能。例如一個表達式的值可能就是一個函數,這個函數可以被作為參數傳遞給另一個函數,或者函數的返回值就是一個函數。同時和Algol類的語言比較接近的是,ML的語法象命令型的,而且用起來象用Algol家族的很多比較新的後代們一樣方便。而且ML有并行擴展,可以用來寫并行系統;甚至還有面向對象擴展。

John C. Mitchell在他的Concepts in Programming Langugaes一書中使用ML來展示Algol類語言、Lisp類語言、以及并行語言和面向對象語言中的概念。

ML是Robin Milner主管LCF項目時設計的。LCF項目是受Dana Scott給出的一組邏輯原則啟發而設立的,緻力于開發一種“可計算函數邏輯”(Logic of Computable Functions)。Robin Milner的目标是構造一個方便實用的系統,來自動的或者半自動的證明函數程序中一些有趣的性質。他的LCF項目于1970年在Standford開始,并于1980年代在Edinburge繼續進行。期間取得了很多重要進展,并且激發了相關領域的一系列研究工作。

ML是作為LCF項目的元語言(Meta Language)設計的,這也是其名字的來曆。它的最初用途是寫一些可以生成數學證明的程序。今天,大多數著名的推理系統都是用ML寫的。

目前ML有兩個發展分支:Standard ML和Caml。

大多數SML編譯器的行為方式都是交互式的:用戶一條一條輸入語句,編譯器一一給出反饋。看起來象Logo或者Basic解釋器一樣。但是其實用戶輸入的程序是被先編譯再執行的(其中細節大家可以從SML/NJ編譯器的相關文檔和論文中找到)。

ML的相關資源

SML New Jersey --> http://www.smlnj.org/

最著名的SML編譯器——Standard ML New Jersey的官方網站。其中還可以找到很多SML相關的内容

Programming in Standard ML --> http://www.cs.cmu.edu/afs/cs/usr/rwh/public/www/introsml/

教科書——Programming in Standard ML。

将Emacs作為SML的開發環境

目前有兩個常用的SML的Emacs mode。一個是 Stefan Monnier寫的,功能強大一些。可以從這裡下 載。SML/NJ的網站上有它的文檔。

一個在線教程

Programming in Standard ML '97: On-line Tutorial --> http://www.dcs.ed.ac.uk/home/stg/NOTES/

SML的Basic Library文檔

如果要用ML寫能實際幹點事情的程序,離了Standard ML Basic Library是不行的。SML/NJ編譯器安裝時已經包含了Basic Library,你可以直接使用。

ML編程環境的配置

在Windows環境下使用Emacs作為ML的集成開發環境。下面關于Emacs和SML在Windows下的配置說明其實同樣适合于各種Unix類操作系統)。這裡有一副抓圖:在左邊的frame中編輯好SML源程序後,按下C-c C-b,程序就交付給運行在右邊frame中的SML編譯器了。你也可以直接在右邊的frame中交互式的輸入SML程序。

為了配置這個環境我安裝了GNU Emacs for Windows(你也可以用XEmacs for Windows)、SML編譯器SML/NJ(你也可以用其他編譯器,比如Moscow ML,Poly/ML)、Emacs的SML mode。安裝和配置步驟如下:

下載和安裝GNU Emacs for Windows

下載和安裝SML New Jersey編譯器

下載和安裝Emacs的SML major mode。具體的方法如下:

在你的Emacs安裝目錄(例如F:\Program Files\emacs-21.3)下建一個子目錄叫site-lisp。如果已經有了就不用建了。

在其中建一個子目錄叫sml-mode

将你下載的SML major mode壓縮包解開,将其中所有.el文件拷貝到site-lisp/sml-mode子目錄下

編輯site-lisp中的site-start.el,加入兩行:

(add-to-list 'load-path "F:/Program Files/emacs-21.3/site-lisp/sml-mode")

(load "sml-mode-startup")

在PATH環境變量裡包含SML編譯器所在的目錄。我的是f:\sml\bin。

啟動Emacs後,敲 M-x run-sml就可以在Emacs中啟動一個SML交互環境。

如果用 M-x sml-mode就将當前buffer的major mode設置為sml-mode,你會發現其中的SML代碼被語法高亮顯示了。如果沒有語法高亮,你可以在Emacs的配置文件(對于Windows版本的GNU Emacs和XEmacs而言是C:\.emacs,對Unix版本的是~/.emacs)中加入一行:

Syntax highlight

(global-font-lock-mode t)

從例子看ML編程風格

通常大家學習編程都是從命令式語言開始的。和函數示語言不同,命令式語言以語句作為基本單位。Algol家族的所有語言都是命令式語言,ML也不例外。因此學習ML不像學習Scheme那樣需要完全轉換一套思路。但是ML繼承了函數式語言的很多特征,而且也有自己的一些特點。

線性數據結構

程序中總要定義數據結構。常用的定長線性結構包括:Pascal的record,C的struct,C++和Java的class。在ML中我們通常用tuple,即用圓括号括起來的,用逗号分隔的若幹項元素。

Tuple是個線性結構,可以用整數索引。比如

#1(1, 2.0, "apple") = 1

#2(1, 2.0, "apple") = 2.0

#3(1, 2.0, "apple") = "apple"

和Algol類語言的數組不同的是,tuple中各個元素的類型可以不一樣。

C++的boost模闆庫中提供了一個模闆tuple,模仿ML/Scheme的tuple,使C++程序員可以将不同類型的數據組織成一個便于訪問的線性結構。

函數的嵌套定義

ML和大多數Algol類語言一樣支持函數的嵌套定義(包括Algol 60、Algol 68和Pascal,但是C是例外)。

如果函數A和函數B互相嵌套調用(indirect recursion),則源程序中可以将B的函數體定義在 A的函數體内,或者A的定義在B的函數體内。具體采用那一種,要看外界是調用A還是B。

函數addqueen和其内部函數try就是這樣的例子。顯然addqueen是要被外部調用的。

用尾部遞歸(tail recursion)代替循環

如果用Algol類語言(例如 Pascal和C)來寫函數addqueen,其中需要一個循環,從某行的第一個位置開始,判斷如果在這個位置上放一個皇後是否可以使得其不和前面已經放上的皇後沖突,而且後面還可以繼續放滿皇後。而ML中這個循環用遞歸函數tryARow表示。

純表達式(pure expression)風格

大多數Algol類語言對機器的抽象是以内存為中心的,即變量和對象(object)對應内存中的存儲區域,賦值語句對應機器的訪存操作,所以程序中有大量的賦值語句。ML也支持賦值,但是通常建議采取的風格是類似Lisp和Scheme的純表達式風格,避免賦值操作。

例如如果用C來描述n皇後問題,通常我們會設計一個數據結構描述棋盤(和ML程序一樣),然後定義這個數據結構的一個實例(可能是個全局變量)。算法的主要工作是通過賦值修改這個實例的内容。

而例子中的ML代碼中經典的一段是函數place。這是修改棋盤數據結構的代碼。但是并沒有使用賦值,而是産生了一個新的數據結構實例,其内容和參數略有區别(放上了一個新的皇後)。

純表達式的使用要求程序員先對程序考慮得非常細緻才能動筆(動手?),因此使得程序邏輯更加清晰。(這和literate programming的思想是一緻的。)但是目前的硬件機器是以内存為中心設計的,所以純表達式語言的實現(編譯器和解釋器)的效率依靠于設計者多費心思。ML就是通過靜态作用域(statically scoping)和uniform data representation等特點結合起來達到高效的。

相關詞條

相關搜索

其它詞條