为什么 `filter` 使用高阶出现类型?
Why does `filter` work with higher-order occurrence typing?
在 Racket 的主页上,他们展示了这个例子:
#lang typed/racket
;; Using higher-order occurrence typing
(define-type SrN (U String Number))
(: tog ((Listof SrN) -> String))
(define (tog l)
(apply string-append (filter string? l)))
(tog (list 5 "hello " 1/2 "world" (sqrt -1)))
我知道在出现类型中,像 (if (string? v) ...)
这样的表达式会将 v
标记为在真正的分支中具有 String
类型。这是因为 string?
的类型有一个过滤器:
> string?
- : (Any -> Boolean : String)
#<procedure:string?>
因此,对于 "higher-order occurrence typing" 与 filter
函数一起使用,我希望 filter
的类型表明谓词类型的过滤器传播到结果类型.但是当我在 REPL 中检查 filter
的类型时,这并没有显示:
> filter
- : (All (a b) (case-> ((a -> Any) (Listof a) -> (Listof b)) ((a -> Any) (Listof a) -> (Listof a))))
#<procedure:filter>
但这不可能是filter
的真实类型,因为b
没有约束!我期待
(All (a b) (a -> Any : b) (Listof a) -> (Listof b))
tldr:为什么 filter
在其 return 类型中出现了一个不受约束的类型变量?
编辑:我正在使用 Racket v6.0
In some cases, asymmetric type information is useful in filters. For example, the filter
function’s first argument is specified with only a positive filter.
Example:
> filter
- : (All (a b)
(case->
(-> (-> a Any : #:+ b) (Listof a) (Listof b))
(-> (-> a Any) (Listof a) (Listof a))))
#<procedure:filter>
The use of #:+
indicates that when the function applied to a variable evaluates to a true value, the given type can be assumed for the variable. However, the type-checker gains no information in branches in which the result is #f
.
换句话说,如果你有下面的例子:
> (filter string? '(symbol 1 2 3 "string"))
- : (Listof String)
'("string")
只有当 string?
returns true
时,系统才会说列表 '(symbol 1 2 3 "string")
的元素是 String
类型。仅在这种情况下传播过滤器谓词的类型。
在 Racket 的主页上,他们展示了这个例子:
#lang typed/racket
;; Using higher-order occurrence typing
(define-type SrN (U String Number))
(: tog ((Listof SrN) -> String))
(define (tog l)
(apply string-append (filter string? l)))
(tog (list 5 "hello " 1/2 "world" (sqrt -1)))
我知道在出现类型中,像 (if (string? v) ...)
这样的表达式会将 v
标记为在真正的分支中具有 String
类型。这是因为 string?
的类型有一个过滤器:
> string?
- : (Any -> Boolean : String)
#<procedure:string?>
因此,对于 "higher-order occurrence typing" 与 filter
函数一起使用,我希望 filter
的类型表明谓词类型的过滤器传播到结果类型.但是当我在 REPL 中检查 filter
的类型时,这并没有显示:
> filter
- : (All (a b) (case-> ((a -> Any) (Listof a) -> (Listof b)) ((a -> Any) (Listof a) -> (Listof a))))
#<procedure:filter>
但这不可能是filter
的真实类型,因为b
没有约束!我期待
(All (a b) (a -> Any : b) (Listof a) -> (Listof b))
tldr:为什么 filter
在其 return 类型中出现了一个不受约束的类型变量?
编辑:我正在使用 Racket v6.0
In some cases, asymmetric type information is useful in filters. For example, the
filter
function’s first argument is specified with only a positive filter. Example:
> filter
- : (All (a b)
(case->
(-> (-> a Any : #:+ b) (Listof a) (Listof b))
(-> (-> a Any) (Listof a) (Listof a))))
#<procedure:filter>
The use of
#:+
indicates that when the function applied to a variable evaluates to a true value, the given type can be assumed for the variable. However, the type-checker gains no information in branches in which the result is#f
.
换句话说,如果你有下面的例子:
> (filter string? '(symbol 1 2 3 "string"))
- : (Listof String)
'("string")
只有当 string?
returns true
时,系统才会说列表 '(symbol 1 2 3 "string")
的元素是 String
类型。仅在这种情况下传播过滤器谓词的类型。