細化類型
細化類型是受謂詞表達式約束的類型。枚舉類型和區間類型是細化類型的語法糖
細化類型的標準形式是{Elem: Type | (Pred)*}。這意味著該類型是其元素為滿足 Pred 的 Elem 的類型
可用于篩選類型的類型僅為 數值類型
Nat = 0.. _
Odd = {N: Int | N % 2 == 1}
Char = StrWithLen 1
# StrWithLen 1 == {_: StrWithLen N | N == 1}
[Int; 3] == {_: Array Int, N | N == 3}
Array3OrMore == {A: Array _, N | N >= 3}
當有多個 pred 時,可以用 ; 或 and 或 or 分隔。; 和 and 的意思是一樣的
Odd 的元素是 1, 3, 5, 7, 9, ...
它被稱為細化類型,因為它的元素是現有類型的一部分,就好像它是細化一樣
Pred 被稱為(左側)謂詞表達式。和賦值表達式一樣,它不返回有意義的值,左側只能放置一個模式
也就是說,諸如X**2 - 5X + 6 == 0之類的表達式不能用作細化類型的謂詞表達式。在這方面,它不同于右側的謂詞表達式
{X: Int | X**2 - 5X + 6 == 0} # 語法錯誤: 謂詞形式無效。只有名字可以在左邊
如果你知道如何解二次方程,你會期望上面的細化形式等價于{2, 3}
但是,Erg 編譯器對代數的了解很少,因此無法解決右邊的謂詞
智能投射
很高興您定義了 Odd,但事實上,它看起來不能在文字之外使用太多。要將普通 Int 對象中的奇數提升為 Odd,即將 Int 向下轉換為 Odd,您需要傳遞 Odd 的構造函數
對于細化類型,普通構造函數 .new 可能會出現恐慌,并且有一個名為 .try_new 的輔助構造函數返回一個 Result 類型
i = Odd.new (0..10).sample!()
i: Odd # or Panic
它也可以用作 match 中的類型說明
# i: 0..10
i = (0..10).sample!
match i:
o: Odd ->
log "i: Odd"
n: Nat -> # 0..10 < Nat
log "i: Nat"
但是,Erg 目前無法做出諸如"偶數"之類的子決策,因為它不是"奇數"等
枚舉、區間和篩選類型
前面介紹的枚舉/區間類型是細化類型的語法糖
{a, b, ...} 是 {I: Typeof(a) | I == a 或 I == b 或 ... },并且 a..b 被去糖化為 {I: Typeof(a) | 我 >= a 和我 <= b}
{1, 2} == {I: Int | I == 1 or I == 2}
1..10 == {I: Int | I >= 1 and I <= 10}
1... <10 == {I: Int | I >= 1 and I < 10}
細化模式
正如 _: {X} 可以重寫為 X(常量模式),_: {X: T | Pred} 可以重寫為X: T | Pred
# 方法 `.m` 是為長度為 3 或更大的數組定義的
Array(T, N | N >= 3)
.m(&self) = ...