摘要: 有的時候,IO的異常處理由于需要一個IOEnv類型的參數而顯得非常麻煩。這個時候我們可以定制自己的一套異常處理系統,從而讓程序變得清晰起來。自己的異常處理系統不同于IO,是沒有副作用的函數集合。下面讓我們看一看如何使用自定義的異常處理系統來分析一個四則運算表達式。
閱讀全文
posted @
2008-12-18 21:23 陳梓瀚(vczh) 閱讀(1449) |
評論 (0) |
編輯 收藏
摘要: 說到底Kernel FP是一個腳本引擎,所以是需要API的。接下來的代碼用來加載一些Kernel FP代碼文件,并執行main函數。
閱讀全文
posted @
2008-12-17 19:15 陳梓瀚(vczh) 閱讀(1636) |
評論 (1) |
編輯 收藏
摘要: 我們知道,循環本身是沒有返回值的。所以在純函數式語言下,跟IO有關的循環才有足夠的副作用來產生價值。于是利用IO Monad,我們就可以實現循環了。循環是一個函數:
閱讀全文
posted @
2008-12-15 07:56 陳梓瀚(vczh) 閱讀(2156) |
評論 (2) |
編輯 收藏
摘要: 前面說過,需要一個語法糖來組織IO,并且在其中的一步產生錯誤的時候立刻返回錯誤。現在我們看一段代碼:
閱讀全文
posted @
2008-12-15 06:22 陳梓瀚(vczh) 閱讀(1477) |
評論 (0) |
編輯 收藏
由于Kernel FP是純的,所以一個函數的輸出只跟輸入有關系,所以從屏幕上輸入文字的函數read是不能定義成func read::string的。因為根據這個性質,read的結果必須是一樣的。所以一定要在每一次read的時候給不同的參數。但是其實沒關系,這個可以用編譯器來解決,就算read的順序是運行時決定的。同樣的問題也出現在Haskell的IO Monad上,由于資料無窮多,我就不詳細解釋了。下面給出沒有語法糖的,能夠正常并確定順序地使用IO函數的一段代碼:
1 data IOError
2 = ioemessage string
3 type IOEnv
4 type IO T = IOEnv -> maybe (pair T IOEnv) IOError
5
6 func read :: IO string alias "demo::read"
7 func readint :: IO int alias "demo::readint"
8 func write :: string -> IO void alias "demo::write"
9 func writeln :: string -> IO void alias "demo::writeln"
10 func iovoid :: IO void alias "demo::iovoid"
11
12 def (>>>) a b = a >>= \p->b
13 func return T :: T -> IO T
14 def return x e = success (pair x e)
15 func (>>=) T1 T2 :: IO T1 -> (T1 -> IO T2) -> IO T2
16 def (>>=) a b e = select a e of
17 case fail message : fail message
18 case success p : select p of
19 case pair x e2 : b x e2
20 end
21 end
22
23 def ioseq ios = foldr iovoid (>>>) ios
24
25 def mainIO_0 =
26 read >>= \name->
27 read >>= \place->
28 writeln ("Hello "+name+" from "+place+".") >>>
29 readint >>= \a->
30 readint >>= \b->
31 writeln (itoa (a+b)) >>>
32 writeln "Press [ENTER] to enter" >>>
33 read
34
35 def mainIO_1 = ioseq (transform writeln ["genius","vczh"])
mainIO_0使用類型系統強制了IO函數的執行順序,mainIO_1證明了IO也是可以使用正常的操作函數去進行復雜操作的。不過mainIO_0那種寫法還是挺不舒服的,這就是語法糖發揮作用的啦。我只需要給出一種相對好看的語法,然后在語法分析的時候翻譯成這樣就行了。
這種寫法的好處是,萬一其中有一個IO出了問題,錯誤信息會直接傳達出去,中斷函數執行。而且整個函數都是在類型系統的保護之下的。
posted @
2008-12-14 22:44 陳梓瀚(vczh) 閱讀(1767) |
評論 (0) |
編輯 收藏
考慮以下代碼:
1 def overloading x = "General overloading"
2 func overloading::string->string
3 def overloading str = "String overloading"
4 func overloading T::list T->string
5 def overloading xs = "List overloading"
這是三個函數,類型分別為:
1 func overloading T1 :: (<T1> -> (system.list system.char)) codefrom 125
2 func overloading :: ((system.list system.char) -> (system.list system.char)) codefrom 127
3 func overloading T1 :: ((system.list <T1>) -> (system.list system.char)) codefrom 129
所以當我們寫overloading的時候,究竟選擇什么呢?三個類型都是可以接受的,而且都是可以完美通過類型推導的。于是我新加了一個規則。首先求出需要的具體類型(可能是含有參數的類型),然后計算從函數類型到具體類型所需要替換的類型參數的個數以及每個類型參數的解,最后計算出一個系數=數量×65536+解的深度和。
深度的規定比較簡單,基本類型深度為1,閉包類型為參數和結果兩種類型的深度的最大值加1,帶有參數的類型等于最大參數深度加1。所以在這個例子上,我們可以得到,T1到list char的解為T1=list char,list char到list char的解為0,list T1到list char的解為T1=char,系數分別是65538、0和65537,所以理所當然地挑選了第二個。下面看例子:
1 def main114 = overloading 1024
2 def main115 = overloading "Genius Vczh!"
3 def main116 = overloading [1,2,3]
下面是運行結果:
1 main114返回值:"General overloading"
2 main115返回值:"String overloading"
3 main116返回值:"List overloading"
posted @
2008-12-14 19:42 陳梓瀚(vczh) 閱讀(1468) |
評論 (0) |
編輯 收藏
現在的Kernel FP已經支持列表語法和操作符語法了。
列表語法為[1,2,3,4,5]。原來是需要寫成list 1 (list 2 (list 3 (list 4 (list 5 empty))))的。不過后面這種寫法仍然是支持的。
操作符可以自定義,凡是僅由“+-*/%<>=!&^|~@#$?”構成,而又不是“|”和“=”的記號都可以視為二元操作符。如果是+、-、*、/、%、<、<=、>、>=、==、!=、^、&&和||的話,優先級跟C++一樣。如果是其他操作符,那么優先級一致而且最低。
因為操作符也是個函數,因此將操作符作為函數使用的時候只需要加一對括號就可以了,不過中間不可以有空格。所以我們就可以定義“+”并寫出下面的代碼:
1 def (+) = iadd
2 def (+) = fadd
3 def (+) = concat
4 def main102 = (+) 1 2
5 def main103 = (+) 1.0 2.0
6 def main104 = (+) "Genius" " Vczh!"
7 def main105 = 1 + 2
8 def main106 = 1.0 + 2.0
9 def main107 = "Genius" + " Vczh!"
下面是執行結果:
1 main102返回值:3
2 main103返回值:3.0
3 main104返回值:"Genius Vczh!"
4 main105返回值:3
5 main106返回值:3.0
6 main107返回值:"Genius Vczh!"
操作符的優先級比函數低,因此sin a + sin b實際上是(sin a)+(sin b)。 于是下面的代碼返回8.0:
1 def main108 = ln (exp 3.0) + ln (exp 5.0)
有了操作符之后,就可以慢慢為IO、Exception等復雜對象建模并且開發語法糖了。
posted @
2008-12-14 08:37 陳梓瀚(vczh) 閱讀(1772) |
評論 (2) |
編輯 收藏
摘要: 為了測試Kernel FP的健壯性以及進行一些bug的排除,一個四則運算式子的分析程序理所當然地就被實現了。代碼如下:
閱讀全文
posted @
2008-12-13 07:13 陳梓瀚(vczh) 閱讀(3350) |
評論 (2) |
編輯 收藏
摘要: 經過1個小時的奮斗,修了3個bug,終于使得Kernel FP能運行的代碼漸漸多了起來。現在可以看看純函數式語言簡潔的代碼及運行結果啦!
下面是很多用于測試的main函數:
閱讀全文
posted @
2008-12-12 10:03 陳梓瀚(vczh) 閱讀(1453) |
評論 (1) |
編輯 收藏
摘要: Kernel FP已經可以運行小程序了。現在還處于測試階段,過于復雜的程序估計是跑不過的。先簡單介紹一下如何在C++調用Kernel FP的代碼。
閱讀全文
posted @
2008-12-10 23:03 陳梓瀚(vczh) 閱讀(1717) |
評論 (2) |
編輯 收藏