Standard ML快餐教程(1) - 初識(shí)

Standard ML快餐教程(1) - 初識(shí)

好久沒寫快餐教程了旱物,下面開始一個(gè)新的系列,關(guān)于函數(shù)式編程語言的系列卫袒。打算寫三種語言:Standard ML宵呛,ocaml和Haskell。
這幾門語言都不是新貴了夕凝,其中Standard ML的知名度可能最低宝穗。因?yàn)镸L系列的影響力,其實(shí)我們已經(jīng)從新的語言如rust等中學(xué)到過這些老語言的很多知識(shí)了÷氡現(xiàn)在我們可能只要將它們還原回去就好逮矛。

運(yùn)行環(huán)境

Standard ML,顧名思義转砖,是ML語言的一種標(biāo)準(zhǔn)規(guī)范须鼎,主要的版本有SML 90和SML 97。
標(biāo)準(zhǔn)的實(shí)現(xiàn)就有很多種方式府蔗。比如以交互式編譯為主要特點(diǎn)的SML/NJ莉兰,還有以優(yōu)化編譯為主要目標(biāo)的mlton。另外一個(gè)重要的Standard ML編譯器是劍橋大學(xué)的David Matthews開發(fā)的poly/ML礁竞,因?yàn)橹耐评碜C明工具Isabelle是使用polyml開發(fā)的。

SML/NJ是由貝爾實(shí)驗(yàn)室的David MacQueen和普林斯頓大學(xué)的Andrew Appel于1986年發(fā)起的杉辙。為了滿足1997年SML的修訂模捂,1998年1月推出了110版本。時(shí)至2020年,主版本號(hào)還是110狂男,比如我現(xiàn)在用的版本是v110.97综看。

SML/NJ的項(xiàng)目主頁在:http://www.smlnj.org/。其源代碼是使用svn管理的岖食。mlton和polyml的源代碼都在github上管理红碑。mlton的地址為:https://github.com/MLton/mlton,ployml的地址為:https://github.com/polyml/polyml/泡垃。

安裝的話析珊,因?yàn)橐陨先N語言工具都屬于比較通用成熟的工具,在mac上的homebrew和Ubuntu之類的主流Linux發(fā)布版本中都有支持蔑穴。
比如在macOS上忠寻,可以使用homebrew進(jìn)行安裝這三種環(huán)境:

brew install mlton
brew install polyml
brew cask install smlnj

在Ubuntu下可以使用下面的命令安裝:

apt install smlnj
apt install mlton
apt install polyml

安裝好之后,運(yùn)行sml命令存和,就可以進(jìn)入sml/nj的交互式環(huán)境奕剃,就可以開始學(xué)習(xí)編寫Standard ML代碼了,"-"是smlnj的提示符:

Standard ML of New Jersey v110.79 [built: Sat Oct 26 12:27:04 2019]
-

我們可以先寫個(gè)HelloWorld程序練練手,比如叫hello.sml:

val a = 1 :int ;
print "Hello,World\n";

smlnj可以通過sml hello.sml來調(diào)用捐腿。
也可以通過mlton hello.sml來編譯纵朋,然后會(huì)生成hello,運(yùn)行hello就可以看到運(yùn)行結(jié)果茄袖。

使用polyc進(jìn)行編譯的時(shí)候操软,會(huì)報(bào)下面的錯(cuò)誤:

poly: : error: Value or constructor (main) has not been declared
Found near PolyML.export (List.nth (CommandLine.arguments (), 3), main)
Static Errors

這是因?yàn)閜olyml需要一個(gè)main函數(shù)。
我們寫個(gè)main函數(shù)吧:

fun main() = print "Hello,World\n";

然后調(diào)用polyc去編譯:

polyc hello2.sml -o hello2

最后運(yùn)行hello2就可以看到運(yùn)行結(jié)果绞佩。

polyml也可以通過poly命令交互式運(yùn)行寺鸥。

Poly/ML 5.8.1 Release

提示符為">"。

數(shù)據(jù)類型

我們可以通過交互式界面來了解下基本數(shù)據(jù)類型的用法品山。

數(shù)字類型

比如我們輸入一個(gè)整數(shù)1:

> 1;
val it = 1: int

我們可以看到胆建,這樣一個(gè)整數(shù)被賦給一個(gè)叫it的默認(rèn)變量,其類型為int.

-1在Standard ML中表示為"~1"肘交,我們來看下:

> val a = 0 - 1;
val a = ~1: int

符點(diǎn)數(shù)是real類型:

> val b = 1e8;
val b = 100000000.0: real

字符串

Standard ML支持字符串類型:

> val d = "Hello";
val d = "Hello": string

布爾值

Standard ML使用true和false兩個(gè)關(guān)鍵字來表示bool類型:

> true;
val it = true: bool
> false;
val it = false: bool
> 1>0;
val it = true: bool

空值

Standard ML的空類型為unit笆载,用來表示一個(gè)空表():

> ();
val it = (): unit
> val g = ();
val g = (): unit

同樣,空的記錄也是unit:

> val x3 = {};
val x3 = (): unit

字符類型

通過“#”涯呻,也可以描述char類型:

> val e = #"c";
val e = #"c": char

ord函數(shù)用來將字符轉(zhuǎn)成整數(shù)凉驻,chr相反將ASCII值轉(zhuǎn)成字符。

> val x4 = ord(#"a");
val x4 = 97: int
> val x5 = chr(65);
val x5 = #"A": char

數(shù)據(jù)結(jié)構(gòu)

元組

元組是使用括號(hào)描述的列表复罐。類型將成為幾個(gè)類型之乘積涝登。
比如(3.0, true)的類型是real * bool.

> val x6 = (3.0, true);
val x6 = (3.0, true): real * bool

列表

不同于元組,列表的元素必須是相同的效诅,用方括號(hào)表示胀滚。
空列表不是unit趟济,也是個(gè)列表類型。

- val a1 = [];
val a1 = [] : 'a list

只要類型相同就可以咽笼,元組也沒問題:

- val a2 = [1,2];
val a2 = [1,2] : int list
- val a3 = ["h","e"];
val a3 = ["h","e"] : string list
- val a4 = [(3,4),(2,5)];
val a4 = [(3,4),(2,5)] : (int * int) list

記錄

類似于哈希表的一種結(jié)構(gòu)顷编,指定key與value:

- val a5 = {name="xulun",age=20};
val a5 = {age=20,name="xulun"} : {age:int, name:string}

如果以數(shù)字1,2,3等為key,則建立的記錄就是元組剑刑。我們看個(gè)例子:

- val a7 = {1=true, 2=3.0};
val a7 = (true,3.0) : bool * real

多賦值

Standard ML支持模式匹配多賦值媳纬,比如我們使用變量元組和值元組,舉個(gè)例子看下就清楚了:

> val (x1,x2) = (1.0, true);
val x1 = 1.0: real
val x2 = true: bool

語句

函數(shù)

可以通過fun來定義函數(shù)施掏,我們直接看個(gè)求平方的例子:

> fun s2 (x:int):int = x*x;
val s2 = fn: int -> int
> s2(4);
val it = 16: int

可以不指定類型钮惠,由系統(tǒng)進(jìn)行推斷:

- fun add1 x y = x + y;
val add1 = fn : int -> int -> int

如果想用浮點(diǎn)類型,可以指定一個(gè)其监,其它由系統(tǒng)推斷:

- fun add2 (x:real) y = x + y;
val add2 = fn : real -> real -> real

注釋

Standard ML使用(**)來寫注釋萌腿。

條件語句

Standard ML支持if then else語句,如果if為真則返回then后面的表達(dá)式抖苦,否則返回else分支的結(jié)果毁菱。

- fun neg1 (x:int) : bool = if x < 0 then true else false;
val neg1 = fn : int -> bool

還記得-1在sml表示為~1吧,我們測試下上面的if判斷:

- neg1(1);
val it = false : bool
- neg1(~1);
val it = true : bool

case語句

通過case語句锌历,可以處理多分支的條件贮庞,每個(gè)條件進(jìn)行自己的匹配。格式為case x of x1 => something1 | x2 => something2 | ...

我們來看個(gè)例子:

- fun grade1(x:int) = case x of 0 => false | 1 => true | x => false;
val grade1 = fn : int -> bool
- grade1(1);
val it = true : bool
- grade1(0);
val it = false : bool
- grade1(100);
val it = false : bool

標(biāo)準(zhǔn)庫

做為一種標(biāo)準(zhǔn)語言究西,Standard ML也支持可移植性的標(biāo)準(zhǔn)庫窗慎。我們可以調(diào)用這些庫像其它語言一樣愉快地編程了。sml的標(biāo)準(zhǔn)庫叫做BASIS卤材。
第一次調(diào)用的時(shí)候遮斥,basis會(huì)被加載進(jìn)來:

- Char.isUpper(#"a");
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[library $SMLNJ-BASIS/(basis.cm):basis-common.cm is stable]
[autoloading done]
val it = false : bool

再來幾個(gè)例子,比如計(jì)算實(shí)數(shù)的絕對(duì)值:

- Real.abs(~1.5);
val it = 1.5 : real

整數(shù)轉(zhuǎn)實(shí)數(shù):

- val a10 = Real.fromInt(1);
val a10 = 1.0 : real

求平方根:

- val a11 = Math.sqrt(2.0);
[autoloading]
[autoloading done]
val a11 = 1.41421356237 : real

字符串連接:

- val a11 = String.concat(["Hello","World"]);
val a11 = "HelloWorld" : string

一起看起來都不錯(cuò)扇丛。類型术吗,分支,函數(shù)等都有了帆精。還有強(qiáng)大的標(biāo)準(zhǔn)庫较屿,恭喜你,已經(jīng)在Standard ML的世界里活下來了 :)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卓练,一起剝皮案震驚了整個(gè)濱河市隘蝎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌襟企,老刑警劉巖嘱么,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異顽悼,居然都是意外死亡拱撵,警方通過查閱死者的電腦和手機(jī)辉川,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拴测,“玉大人,你說我怎么就攤上這事府蛇〖鳎” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵汇跨,是天一觀的道長务荆。 經(jīng)常有香客問我,道長穷遂,這世上最難降的妖魔是什么函匕? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮蚪黑,結(jié)果婚禮上盅惜,老公的妹妹穿的比我還像新娘。我一直安慰自己忌穿,他們只是感情好抒寂,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掠剑,像睡著了一般屈芜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上朴译,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天井佑,我揣著相機(jī)與錄音,去河邊找鬼眠寿。 笑死躬翁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的澜公。 我是一名探鬼主播姆另,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼坟乾!你這毒婦竟也來了迹辐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤甚侣,失蹤者是張志新(化名)和其女友劉穎明吩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體殷费,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡印荔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年低葫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仍律。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘿悬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出水泉,到底是詐尸還是另有隱情善涨,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布草则,位于F島的核電站钢拧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏炕横。R本人自食惡果不足惜源内,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望份殿。 院中可真熱鬧膜钓,春花似錦、人聲如沸伯铣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腔寡。三九已至焚鲜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間放前,已是汗流浹背忿磅。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凭语,地道東北人葱她。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像似扔,于是被迫代替她去往敵國和親吨些。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容