第九章:type、newtype和惰性求值
1.型別別名 type
和data不同,type是一個輕量型的語法,它僅僅是給已經存在的型別提供了一個不一樣的名字,不會定義新的建構函式
在型別檢查時,這個“新”的資料型別和type指代的型別完全等價,編譯器不會區別
type型別別名宣告常常用語簡化型別的書寫
type List a = [a] type IntList = [Int] xs = [1,2,3] :: IntList type Shows = String -> String --別名標記了字串到字串的函式 showsPrec :: Int -> a -> Shows -- showsPrec 接收了一個Int 和a型別的引數,返回一個 String -> String型別的函式
2.新型別宣告 newtype
newtype允許使用者定義一個只包含一個建構函式,且建構函式只接收一個引數的資料型別,而該型別只在程式碼層面發生表面的打包和解包,在底層允許時,打包和解包的過程會消失。
newtype更像是data的一個特例,和type並沒有什麼關係。newtype的寫法和data一樣,但只允許構造一個函式,且建構函式只接收一個引數
newtype之所以不用在執行時額外打包和解包,是因為它直接把建構函式接收引數的盒子上的標籤換成了自己定義的新標籤
newtype比data的速度更快
底 bottom
+底在計算機世界中用來表示無法計算的值 | 在Prelude中的undefined就代表這個值
y= let x = x in x
+我們引入Maybe型別中的Nothing,是用來人為的標記失敗的運算
+和Nothing的型別是Maybe a型別, | 可以出現在任何種類的計算中,所以|可能是任何型別
+如果我們在計算的時候沒有開啟裝有 |的盒子,計算是可以繼續下去的
(||) :: Bool -> Bool -> Bool True || _ = True _ || True = True _ || _ = False True || undefined True || let x =x in x --均返回True undefined || True --程式終止,報錯
+Haskell 中所以的函式行為和||都一樣,
+不包含|的型別叫做底層型別(unlifted type)否則是上層型別(lifted type)
+上層型別構起了Haskell最重要的特性——惰性(Lzay)
3.惰性求值
上面例子中函式的行為稱作惰性計算,相對的是**迫切求值**eager evaluation
短路原理:特定的運算子在判斷某些引數之後,可以不用其他引數立即得出結果的行為
兩種函式行為按需傳遞 call-by-need 和按值傳遞 call-by-value
任務盒 thunk :未計算的盒子
標記語義 denotational semantics / 引用透明原則 referential transparency :隨時隨地可以把一個繫結換成它對應的表示式,而不影響程式的求值
+標記語義的好處:編譯器可以任意替換繫結,或者在不衝突的情況下改變繫結的作用域,實現內聯化簡融合等複雜的變換,而不影響我們書寫的程式的語義
+後果是你無法預測函式呼叫在什麼時候發生
求值過程 和標記語義相對 +:print :sprint :force 除錯求值過程
+我們把完全求值後的表示式稱作常態 normal form
+對於類似"hello"和"world"這樣的求值狀態,我們成為弱常態
+我們引入任務盒、常態和弱常態的概念,實際都是為了解決任務盒堆積的問題
seq和deepseq
+seq強迫計算人物盒
seq :: a -> b -> b ($!) :: (a -> b) -> a -> b
$!函式就是$函式的迫切求值版本,嚴格 strict 版本
force函式,當對 force x 求值時,x會被求值到常態,這相當於是有副作用版本的id函式
GHC的嚴格性分析 strictness analysis
相關文章
- 惰性求值——lodash原始碼解讀原始碼
- 利用 Lambda 表示式實現 Java 中的惰性求值Java
- 利用Lambda表示式進行Java中的惰性求值Java
- 如何用 JavaScript 實現一個陣列惰性求值庫JavaScript陣列
- Python函數語言程式設計系列007:惰性求值Python函數程式設計
- 函式正規化入門(惰性求值與函式式狀態)函式
- 筆記:Haskell函數語言程式設計入門 - 惰性求值簡介筆記Haskell函數程式設計
- JavaFX教程-增量式求值和懶惰求值Java
- 基於 Generator 和 Iterator 的惰性列表
- 函數語言程式設計學習-SICP-LISP-流STREAM的實現-流程式設計思路和惰性/延時求值2函數程式設計Lisp
- Rust中新型別Newtype使用注意點Rust型別
- 3.2.5 表示式求值
- Angular 中使用惰性載入Angular
- JavaScript 函式惰性載入JavaScript函式
- JS中的求值策略JS
- Javascript中的求值策略JavaScript
- JavaScript 中的求值策略JavaScript
- Logstash 中type 和 tags
- angular路由中的惰性載入Angular路由
- JavaScript 專題之惰性函式JavaScript函式
- Swift的惰性初始化方法Swift
- 第九章 表單和登陸爬蟲爬蟲
- Go 中 type var string 和 type var = string 的區別Go
- 編譯錯誤 --- does not name a type和field `XX' has incomplete type編譯
- Java表示式求值引擎 - AviatorJava
- 【區分】Typescript 中 interface 和 typeTypeScript
- ORACLE中%TYPE和%ROWTYPE的使用Oracle
- Wordpress 和 Movable Type 的比較
- pl/sql %type和%rowtype區別SQL
- [譯] Swift 中的惰性序列及其原理Swift
- 編譯錯誤--------:XX does not name a type和field `XX' has incomplete type編譯
- Go 泛型語法又出 “么蛾子”:引入 type set 概念和移除 type list 中的 type 關鍵字Go泛型
- TypeScript 裡 interface 和 type 的區別TypeScript
- <button>和<input type=“button“> 的區別
- <input type="button">和<button>的區別
- PLSQL包和TYPE參考手冊SQL
- ts中的type 和 interface 區別
- HTML中input type="text"和type="password" 顯示的長度不一樣HTML