类型化 Racket 中 `with-handlers` 的意外行为

问题描述 投票:0回答:1

我正在尝试处理键入的球拍中的某些类型的错误。以下代码在类型化和非类型化 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)

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

exception error-handling racket typed-racket
1个回答
0
投票

在普通 Racket 中,

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

我发现你几乎总是必须显式指定函数参数的类型; Typed Racket 通常不会推断它们,而是为它们提供通用的

Any
类型。因此,要满足
raise
的类型:

#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))))
© www.soinside.com 2019 - 2024. All rights reserved.