Scheme/Lisp有類型系統嗎?
看王垠一直在批評Haskell的Hindley-Milner等等,想問問Scheme/Lisp這樣的語言如何
當然有啊,滿屏的
王垠如何先不談,動態類型系統實際上也是靜態類型系統的一種。如果一個語言里所有的值都只有一種類型,那麼這種語言的類型系統就被稱為動態類型系統。
比如以簡化的Scheme為例,data Value
= Fixnum Int
| Symbol String
| Cons Value Value
| Nil
| T
| F
無論是數字,符號,列表,都是一種類型。
在此之上寫一個big-step的解釋函數eval :: Value -&> Value
就留作作業了:)
擴展閱讀:Dynamics Language Are Static LanguagesBenjamin Pierce: Types and Programming LanguagesWrite Yourself a Scheme in 48 Hours王垠和他的老師 Friedman 一樣「不喜歡一切複雜的東西。」scheme的作者Sussman說 scheme 是也有類型系統的,但是程序員要自己記住對象的屬於類型。。。。。==========略有有篡改 逃)
scheme方言racket有typed-racket.可以在racket中使用類型系統
* lisp的類型 從lisp七條公理的角度出發
- quote
- atom?
- eq?
- car
- cdr
- cons
- cond
可以發現,lisp其實只有這樣幾個類型:
- 空,即 (quote ()),有很多方言把它叫做 nil什麼的
- atom, 即(quote symble) 這樣的, 可以用atom?來判斷
- 然後還有一個類型就是bool類型,即eq? atom?這種操作的結果
- pair, 即用cons構造的那個數據結構。
- A. (quote ()) 是不是 atom
- B. cond的時候,(quote ()) 是不是當做 假
- C. cond裡面,非(quote ())的atom是不是當做真
- D. cond裡面,所有的pair是不是都當作真
而且進一步說,就算以上的回答是 yes, 也可能是做了類型推斷的結果。
* 那整數、字元串、浮點數這些是怎麼回事?
比如我可以這樣來構造自然數:;; #f是bool類型,表示false, #t是bool類型,表示true, add是 (quote add)的縮寫。
;; reverse我就不定義了
(define #f (eq? a b))
(define #t (eq? a a))
(define (and x y)
(cond (x (cond (y #t) (#t #f))) (#t #f)))
(define (not x)
(cond (x #f) (#t #t)))
(define (null? x)
(eq? x ()))
(define (reverse x)
(let lp ((r ()) (y x))
(cond ((null? y) r)
(#t (lp (cons (car y) res) (cdr y))))))
(define (nature-number x)
(let ((n x))
(lambda (op . y)
(cond ((eq? op add)
(let lp ((res ()) (f #f) (rx x) (ry y))
(let ((cx (cond ((null? rx) #f) (#t (car rx))))
(cy (cond ((null? ry) #f) (#t (car ry))))
(rex (cond ((null? rx) ()) (#t (cdr rx))))
(rey (cond ((null? ry) ()) (#t (cdr ry)))))
(cond ((and (null? rex) (and (null? rey) (not f))) res)
(#t
(cond ((and cx (and cy f)) (lp (cons #t res) #t rex rey))
((and (not cx) (and cy f)) (lp (cons #f res) #t rex rey))
((and cx (and (not cy) f)) (lp (cons #f res) #t rex rey))
((and cx (and cy (not f))) (lp (cons #f res) #t rex rey))
((and (not cx) (and (not cy) f)) (lp (cons #t res) #f rex rey))
((and (not cx) (and cy (not f))) (lp (cons #t res) #f rex rey))
((and cx (and (not cy) (not f))) (lp (cons #t res) #f rex rey))
((and (not cx) (and (not cy) (not f))) (lp (cons #f res) #f rex rey))))))))))))
(define (+ x y) (reverse (x add y)))
; 以上定義的是自然數加法,自然數的表達是 (#t #f #t #t) 的二進位,而且是big endian。
從上面的定義看到,這個加法其實沒有對y做任何類型檢查。
如果y是這樣一個 list : (a (b c) () d)的話,
如果A. cond認為 a b (b c)都是 #t, 而()是#f的話,那麼y就變成 ( #t #t #f #t)了B. cond做強類型檢查,報錯的話,那麼上面的加法就做不成了以上的 A 就是一種類型推斷, B就是強類型檢查。
同理可以定義減法,然後就有了整數,然後定義乘法和除法,就可以定義有理數,再然後就可以定義實數了,以及整個數學系統。這個大約就是類型論的出發點吧。
直接點回題主的問題: 王垠不是說類型本身有問題,他說的是HM類型推斷有問題。Typed racket應該算
基本上所有語言都有類型系統…要不你來跟我說一下字元串加整數等於幾?(JS這種自帶這種類型變換的不算)只不過編程語言分為動態類型(運行時進行類型檢查)和靜態類型(編譯時進行類型檢查)這兩種(其實還有比較另類的,先不說),scheme是動態類型的,所以會感覺不到類型系統而已
Typed/racket
沒有可以讓它有。有可以讓它沒有。
推薦閱讀:
※Lisp 對於編程語言的發展有哪些貢獻?
※Functional Programming 說的就是 Lambda Calculus 嗎?
※一鍵跳轉到定義!highlight-symbol增強攻略
※入門 Lisp 有哪些在線資料?
※Lisp 能被用來幹什麼?
TAG:Lisp | Scheme | 類型系統 | CommonLisp |