类型化球拍中“with-handlers”的意外行为

Unexpected behaviour of `with-handlers` in typed Racket

提问人:Tom Price 提问时间:11/5/2023 更新时间:11/5/2023 访问量:20

问:

我正在尝试处理键入的 Racket 中的某些类型的错误。以下代码在类型化和非类型化 Racket 中都按预期工作

(with-handlers
    ([exn:fail:contract:divide-by-zero?
      (lambda (e)
        (raise e))])
    (let ([x 0]
          [y 1])
      (display (/ y x))))

导致错误消息

/: division by zero

在未打字的 Racket 中稍作阐述:

(with-handlers
    ([exn:fail:contract:divide-by-zero?
      (lambda (e)
        (displayln "oops!")
        (raise e))])
    (let ([x 0]
          [y 1])
      (display (/ y x))))
oops!
/: division by zero

但在键入的 Racket 中给出以下错误消息:

Type Checker: No function domains matched in function application:
Domains: (U (Rec flat (U (Immutable-HashTable flat flat) (Immutable-Vectorof flat) (Pairof flat flat) Boolean Bytes Char Complex Keyword Null String Symbol)) exn) Any 
         (U (Rec flat (U (Immutable-HashTable flat flat) (Immutable-Vectorof flat) (Pairof flat flat) Boolean Bytes Char Complex Keyword Null String Symbol)) exn) 
Arguments: Any
 in: (raise e)

有人可以解释一下这里发生了什么,或建议解决方法吗?

异常 错误处理球 类型球拍

评论


答:

1赞 Shawn 11/5/2023 #1

虽然在普通的 Racket 中,要提出的第一个参数可以是任何值,但由于某种原因,在 Typed Racket 中,它仅限于特定类型的列表,包括结构的层次结构。exn

我发现您几乎总是必须显式指定函数的参数类型;Typed Racket 通常不会推断它们并赋予它们通用类型。因此,要满足 的类型:Anyraise

#lang typed/racket/base

(with-handlers
    ([exn:fail:contract:divide-by-zero?
      (lambda ([e : exn]) ; The type of a struct is usually the name of the struct
        (displayln "oops!")
        (raise e))])
    (let ([x 0]
          [y 1])
      (display (/ y x))))

评论

0赞 Shawn 11/5/2023
有趣的是,为什么你的第一个例子在TR中有效;我怀疑像这样的表达式是在类型检查完成之前变成的,而更复杂的表达式不是这样内联的。(lambda (x) (f x))f
0赞 Tom Price 11/6/2023
谢谢!在我最初的问题中,我忘了提到我也尝试过,它给出了与 TR 相同的结果。所以你也回答了一个我没有问:)的问题lambda ([e : Any])lambda (e)