序數
我們將通過實現自定義型別序數來了解如何實現自定義比較。為簡化實現,我們將重點關注這些數字的一小部分:所有序數最多但不包括ε0。我們的實施重點是簡單,而不是速度; 但是,實施也不慢。
我們按照康托爾的正常形式儲存序數。因為序數算術不是可交換的,所以我們將採用儲存最重要術語的通用約定。
immutable OrdinalNumber <: Number
βs::Vector{OrdinalNumber}
cs::Vector{Int}
end
由於 Cantor 正規形式是唯一的,我們可以簡單地通過遞迴相等來測試相等性:
Version >= 0.5.0
在 v0.5 版本中,有一個非常好的語法可以緊湊地執行此操作:
import Base: ==
α::OrdinalNumber == β::OrdinalNumber = α.βs == β.βs && α.cs == β.cs
Version < 0.5.0
否則,將函式定義為更典型的:
import Base: ==
==(α::OrdinalNumber, β::OrdinalNumber) = α.βs == β.βs && α.cs == β.cs
要完成我們的訂單,因為這種型別有一個總訂單,我們應該過載 isless
函式:
import Base: isless
function isless(α::OrdinalNumber, β::OrdinalNumber)
for i in 1:min(length(α.cs), length(β.cs))
if α.βs[i] < β.βs[i]
return true
elseif α.βs[i] == β.βs[i] && α.cs[i] < β.cs[i]
return true
end
end
return length(α.cs) < length(β.cs)
end
為了測試我們的訂單,我們可以建立一些方法來生成序數。當然,零是通過 Cantor 正常形式的條款獲得的:
const ORDINAL_ZERO = OrdinalNumber([], [])
Base.zero(::Type{OrdinalNumber}) = ORDINAL_ZERO
我們可以定義一個 expω
來計算ω^α
,並用它來計算 1 和ω:
expω(α) = OrdinalNumber([α], [1])
const ORDINAL_ONE = expω(ORDINAL_ZERO)
Base.one(::Type{OrdinalNumber}) = ORDINAL_ONE
const ω = expω(ORDINAL_ONE)
我們現在有一個關於序數的全功能排序函式:
julia> ORDINAL_ZERO < ORDINAL_ONE < ω < expω(ω)
true
julia> ORDINAL_ONE > ORDINAL_ZERO
true
julia> sort([ORDINAL_ONE, ω, expω(ω), ORDINAL_ZERO])
4-element Array{OrdinalNumber,1}:
OrdinalNumber(OrdinalNumber[],Int64[])
OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[],Int64[])],[1])
OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[],Int64[])],[1])],[1])
OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[],Int64[])],[1])],[1])],[1])
在最後一個例子中,我們看到序數的列印可能會更好,但結果是預期的。