我可以通过手动编写比较器来比较两个自然数:
is-≤ : ℕ → ℕ → Bool
is-≤ zero _ = true
is-≤ (suc _) zero = false
is-≤ (suc x) (suc y) = is-≤ x y
但是,我希望标准库中有类似内容,所以我不是每次都写不出来。
我能够找到_≤_
运算符in Data.Nat,但它是一个参数化类型,基本上包含" proof"一个特定的数字小于另一个(类似于_≡_
)。有没有办法使用它或其他东西来了解哪个数字小于另一个数字"在运行时" (例如,返回相应的Bool
)?
我试图解决的更大问题:
readNat : List Char → Maybe (ℕ × List Char)
函数。它试图从列表的开头读取自然数;稍后将成为sscanf
。digit : Char → Maybe ℕ
辅助函数,它将解析一个十进制数字。primCharToNat c
与primCharToNat '0'
,primCharToNat '1'
进行比较,并决定是否返回None
或(primCharToNat c) ∸ (primCharToNat '0')
答案 0 :(得分:4)
@gallais在评论中建议的解决方案:
open import Data.Nat using (ℕ; _≤?_)
open import Data.Bool using (Bool)
open import Relation.Nullary using (Dec)
is-≤ : ℕ → ℕ → Bool
is-≤ a b with a ≤? b
... | Dec.yes _ = Bool.true
... | Dec.no _ = Bool.false
这里我们匹配_≤_
使用with
- 子句可判定的证据。人们可以在更复杂的功能中使用它。
@ user3237465对此答案的评论提出建议:您还可以使用简写⌊_⌋
(\clL
/ \clR
或\lfloor
/ \rfloor
){ {3}}并且无需is-≤
:
open import Data.Nat using (ℕ; _≤?_)
open import Data.Bool using (Bool)
open import Relation.Nullary.Decidable using (⌊_⌋)
is-≤ : ℕ → ℕ → Bool
is-≤ a b = ⌊ a ≤? b ⌋
另一种方法是使用does this exact pattern matching,它还提供更多信息(例如两个数字之间的差异):
open import Data.Nat using (ℕ; compare)
open import Data.Bool using (Bool)
open import Relation.Nullary using (Dec)
is-≤' : ℕ → ℕ → Bool
is-≤' a b with compare a b
... | Data.Nat.greater _ _ = Bool.false
... | _ = Bool.true
is-≤3' : ℕ → Bool
is-≤3' a with 3 | compare a 3
... | _ | Data.Nat.greater _ _ = Bool.false
... | _ | _ = Bool.true
请注意,由于某种原因,compare
使用常量值compare
。