2015讀書進度[漆楚衡]-《Write Yourself a Scheme in 48 Hours》
2015讀書進度-《Write Yourself a Scheme in 48 Hours》
這周開始了《Write Yourself a Scheme in 48 Hours》,這本書跟《自制程式語言》有些相似,可以跟《自制程式語言》的第一部分對比著讀。
跟《Write》相似的還有《SICP》的第4章,《The Little Schemer》和《The Seasoned Schemer》的最後一章。
這三個都是在Scheme本身下實現Scheme。 說來慚愧,在看《自制》和《Write》的過程中,終於領會到……自己其實沒有看懂這三本書……
主要概念
《Write》是一本Haskell的入門書,走實踐路線,通過實現Scheme告訴你Haskell中的一些概念。
- IO Monad
- Either (Monad)
- Error Monad
- Existential Types——展示語言擴充,實現異態列表
- Monad Transformer——以前沒搞懂,這裡的也沒看太懂
- IORef——通過IO實現可變物件
- 檔案處理API
- Parsec——haskell的分析器,對比lex/yacc……
- ……
我碰到的難點
這本書的內容還是挺簡單的,不過裡面有些地方我還是花了點時間才看懂的,還有些地方目前還不太懂。
- 異常:這只是稍微有點麻煩,總體上比這本書的平均難度要高一點,要仔細讀一讀第四章。
- 可變數:Haskell本身是沒有可變數的,可變數都遮蔽在IO Monad中了,不過Scheme中沒有那麼嚴格的區分。
對於IO Monad和Either(作為Monad時),始終要記得所有操作都是用
bind
串聯起來的。也就是函式的最後一個引數總是Monad。 在引入可變數之前,這兩個Monad井水不犯河水,IO是程式的最外層,Either的操作extractValue拆解了,影響範圍不大。 引入可變數之後,二者開始出現交集,用Monad Transformer解決。 - Monad Transformer,這個東西之前就不太懂。雖然在這本書中不需要弄懂內部原理就可以繼續讀下去。不過心中還是有疑惑,相關程式碼也只是一知半解(好吧,主要是有藉口看不懂了……)。
- 函式進化史:函式處理是書中程式碼重寫次數比較多的地方,需要仔細追蹤演化軌跡
- 第三章:實現最基本的算術運算,apply第一次出現,在apply中實現了一個表查詢
- 第五章:一大波關係運算降臨,實質改變不大
- 第八章:引入變數後,第八章引入使用者定義函式。也引入了跟可變性有關的幾個special form 函式真正成為值,廢除apply中的表查詢。不論原生函式(之前只有原生函式)還是使用者定義函式,都放在Env中,按名索取。
- 引入IO Port 因為IO Port與之前的原生函式型別不相容,所以需要另外有張函式表。 注意,因為Env中儲存的是LispVal(所有型別),所以所有函式(原生,IO,自定義)都可以放在Env中。
一些細節
List VS DottedList
在這本書才明白scheme中普通的列表'(a b)
和點列表'(a b . c)
的區別在於:
- 前者是
(cons 'a (cons 'b '()))
- 後者是
(cons 'a (cons 'b 'c))
即最內部是否為'()
load(scheme)
函式都是在apply中應用的,而函式應用一直都不需要Env。所以apply不知道呼叫函式時的Env
load需要讀取檔案,再在Env(似乎是全域性Env)中掛載檔案裡程式碼的執行結果
書中的解決方法是通融一下,讓load成為special form。不過這樣load就不是函式了,不能放入Env,不能傳來傳去。
我想了一下,也許也可以分解一下:第一部分是一個IO函式,第二部分是Env設定(special form或函式),第二部分先藏在Env中,取一個Scheme非法名稱。 再有一個load對應的函式,首先呼叫IO函式取得掛載表,再用第二個函式掛載。
另外也可以直接暴露全域性Env,說不定還有其它用途(危險)呢。
異常,與Either Monad
雖然書中出現了一個Error Monad,不過好像沒什麼存在感,異常處理主要是對Either的一些操作。
Either a b
型別提供了兩個值構造子Left a
,Right b
。一般約定Left a
表示a型別錯誤資訊,Right b
表示一個正常的b型別的值
Either主要是作為一個Monad來用的,另有兩個實用函式:
throwError
丟擲異常catchError
處理異常
有以下程式碼
fun :: Int -> Either String String
fun x
| x > 0 = return . show $ x
| otherwise = throwError "Positive please."
slover :: String -> Either String String
slover str = return str
-- try block
a :: Either String Int
a = Left "No number here"
b :: Either String Int
b = Right (-1)
test1 = catchError (a >>= fun) slover
test2 = catchError (b >>= fun) slover
-- extractValue
v1 = let Right x = test1 in x
v2 = let Right x = test2 in x
在C++中,也許可以寫成下面這樣
string v1, v2;
try {
a = getInt();
b = -1;
v1 = test1(fun(a));
v2 = test2(fun(b));
} catch(Error_V1 e) {
v1 = slover(e);
} catch(Error_v2 e) {
v2 = slover(e);
}
有了熟悉的參照,Either Monad就很好理解了。
兩種異常的目的是一樣的:如果發生異常,則立刻放棄後續執行,跑去catch處理異常。
可以看出來,Either Monad(大部分以Either a b型別結尾的程式碼)就像是在try塊中的程式碼一樣受到“監視”
slover和fun算是例外,不過它們類比於try塊中呼叫的函式。它們也是(必須是)Either a b型別結尾的程式碼,這似乎可以看作受查異常?
不同之處在於catch,Haskell中的異常處理是通過函式指定的,而C++中是通過型別指定的。
三種函式和set!
最終的函式系統分成三部分:
- 原生簡單函式
- 原生IO函式:需要在IO Monad下操作
- 使用者定義函式
除此之外,函式中還會呼叫set行為對Env進行操作。
我當時有些疑問:使用者定義函式會組合這些,特別是IO函式和set行為,會不會產生某種混亂?(參考剛剛想過的load)
思考之後發現,不會。我把Haskell對Haskell函式的要求延伸到Scheme中去了(@_@)。
始終記住,對於現在的語境,Scheme對於Haskell來說只不過是字串。
Scheme中會出現上述幾種函式的交織,但這不關Haskell的事。
這種相互遞迴是Scheme的語義,而在Haskell中,對Scheme分析樹(列表)的執行是在eval(和apply)的遞迴上進行的。
對於一個Scheme普通函式,它內部呼叫set!的操作反映到Haskell中,就是在解釋這個函式時遞迴呼叫eval。
在eval中根據LispVal的值構造子,分派出針對set special form的操作。
原生函式和預定義的special form不會彼此影響,而使用者定義函式在eval時不過是不斷遞迴降解應用eval的過程。
相關文章
- 2015讀書進度-《自制程式語言》[漆楚衡]
- 2015讀書進度[fairjm]AI
- 取捨於得失之間:權衡Java EE 5.0 & Seam & Spring & YourselfJavaSpring
- 2015讀書總結
- 讀書筆記=2015.7.25筆記
- 【閱讀記錄】App介紹(記錄你的每一次讀書進度)APP
- ALi CTF 2015 write up
- 什麼是專案管理?《專案計劃、進度與控制》-讀書系列專案管理
- 2015年讀書總結和2016年讀書計劃
- MySQL 8.0 Reference Manual(讀書筆記48節--Optimizing SELECT Statements(3))MySql筆記
- 2015讀書學習之路[蒼松]
- 2015年讀書學習計劃
- 2015年閱讀書單總結
- Be Tolerant of Yourself But Strict with Others?
- 讀取檔案大小-列印進度條
- 2015年讀書學習計劃-樂樂爹
- [轉]how to introduce yourself in the interviewView
- 【新特性速遞】進度條,進度條,進度條
- 維度處理-資料倉儲-讀書筆記(四)筆記
- Scheme嚐鮮Scheme
- [swift進階]的讀書筆記寫完啦~Swift筆記
- 《讀書與做人》讀書筆記筆記
- 解讀《百度網頁質量白皮書》潛臺詞網頁
- IT工作者的真實讀書進階路徑
- 155、楚江懷古
- Intent scheme URL attackIntentScheme
- Laravel Scheme排程LaravelScheme
- 抖音快手URL SchemeScheme
- URL Scheme的使用Scheme
- Xcode 修改 schemeXCodeScheme
- 仿Windows畫板噴漆筆刷效果Windows
- Get yourself a femdom Superior If you are truly submissive in ShanghaiAI
- 讀書那點事——淺談2015,暢談2016
- [swift 進階 advanced swift]讀書筆記-第六章:字串 C7P1 不再固定寬度Swift筆記字串
- 進度管理
- ajax進度條 非同步下載進度條非同步
- 2015年Goodreads讀者票選最佳科技/科幻圖書揭曉Go
- Final Cut Pro 中文基礎教程(48)精確度編輯