从 Typed Racket 联合中提取类型
Extract a type from a Typed Racket union
我有一个功能,有点像 assoc
,在列表中搜索一个符号,returns #f
或列表中的位置。
此函数的 return 类型应该是 #f
和 Natural
、(U #f Natural)
.
的并集
但是当我想将该值用作数字时,它总是类型不匹配,因为该值不仅是一个自然值,而且实际上是一个联合。
如何提取 Natural 值并避免类型不匹配错误?
Typed Racket 有一项名为 Occurrence Typing 的功能,它允许您使用谓词和断言来过滤值的类型。基本思想是 string?
、empty?
和 number?
等谓词可以根据程序的控制流 过滤 类型。
为了说明这一点,请看这个例子:
(: nat/#f->nat ((U Natural False) -> Natural))
(define (nat/#f->nat n)
(if n n
(error "Expected a number, given " n)))
这将进行类型检查,因为如果采用第一个分支,则 n
不能是 #f
,因此它必须是 Natural
。在第二种情况下,函数只是出错而不是 return,所以类型仍然成立。
在大多数情况下,您不会只是简单地在失败情况下出错,而是会提供某种替代行为。这仍然允许您在主体本身内细化类型。
(define n : (Option Natural) #f)
(cond
[n
; do something with n as a number
(+ n 1)]
[else
; do something else
(void)])
在第一个案例中,n
的类型被细化为Natural
,因此可以这样使用。
如果您实际上 只想在类型不匹配时抛出错误,则可以使用 assert
or cast
。前者实际上是一个派生概念,它基本上执行与上面第一个示例相同的检查。你这样使用它:
(assert n number?) ; now n is a number, and if it isn't, an error is thrown
(+ n 1)
cast
形式有点不同,因为它指定 types 而不是谓词。这意味着您可以像这样使用它:
(+ (cast n Natural) 1)
如果发现 n
实际上不是 Natural
,这也会引发错误,否则,整个表达式变为 Natural
.[=30= 类型]
做这样的事情:
(define i (assoc ...))
(cond
[i <use-i-here>]
[else <raise-error>])
从 (define i (assoc ...))
我们知道 i
具有 assoc
的 return 类型,即它是 #f 或自然数。在 cond 子句 [i <use-i-here>]
中,仅当 i
不是 #f
时才会评估 <use-i-here>
,因此类型检查器知道 <use-i-here>
i
将顺其自然。
我有一个功能,有点像 assoc
,在列表中搜索一个符号,returns #f
或列表中的位置。
此函数的 return 类型应该是 #f
和 Natural
、(U #f Natural)
.
但是当我想将该值用作数字时,它总是类型不匹配,因为该值不仅是一个自然值,而且实际上是一个联合。
如何提取 Natural 值并避免类型不匹配错误?
Typed Racket 有一项名为 Occurrence Typing 的功能,它允许您使用谓词和断言来过滤值的类型。基本思想是 string?
、empty?
和 number?
等谓词可以根据程序的控制流 过滤 类型。
为了说明这一点,请看这个例子:
(: nat/#f->nat ((U Natural False) -> Natural))
(define (nat/#f->nat n)
(if n n
(error "Expected a number, given " n)))
这将进行类型检查,因为如果采用第一个分支,则 n
不能是 #f
,因此它必须是 Natural
。在第二种情况下,函数只是出错而不是 return,所以类型仍然成立。
在大多数情况下,您不会只是简单地在失败情况下出错,而是会提供某种替代行为。这仍然允许您在主体本身内细化类型。
(define n : (Option Natural) #f)
(cond
[n
; do something with n as a number
(+ n 1)]
[else
; do something else
(void)])
在第一个案例中,n
的类型被细化为Natural
,因此可以这样使用。
如果您实际上 只想在类型不匹配时抛出错误,则可以使用 assert
or cast
。前者实际上是一个派生概念,它基本上执行与上面第一个示例相同的检查。你这样使用它:
(assert n number?) ; now n is a number, and if it isn't, an error is thrown
(+ n 1)
cast
形式有点不同,因为它指定 types 而不是谓词。这意味着您可以像这样使用它:
(+ (cast n Natural) 1)
如果发现 n
实际上不是 Natural
,这也会引发错误,否则,整个表达式变为 Natural
.[=30= 类型]
做这样的事情:
(define i (assoc ...))
(cond
[i <use-i-here>]
[else <raise-error>])
从 (define i (assoc ...))
我们知道 i
具有 assoc
的 return 类型,即它是 #f 或自然数。在 cond 子句 [i <use-i-here>]
中,仅当 i
不是 #f
时才会评估 <use-i-here>
,因此类型检查器知道 <use-i-here>
i
将顺其自然。