Typed Racket 是否提供了类型安全的 list-ref 函数?

问题描述

Typed Racket 是否提供了类型安全的 list-ref 函数

如果您尝试访问超出范围的索引,list-ref 函数似乎会抛出错误

> (require typed/racket)
> (list-ref '(1 2 3) 100)
; list-ref: index too large for list
;   index: 100
;   in: '(1 2 3)

list-ref 在给定其类型的情况下返回错误是有道理的:

> list-ref
- : (All (a) (-> (listof a) Integer a))

我想一个类型安全的版本会有如下类型:

(: list-ref (All (a) (-> (listof a) Integer (Option a)))

如果 Typed Racket 的某个地方提供了这个类型安全的 list-ref 函数,我将如何找到它?

如果这个类型安全的 list-ref 函数不存在,那为什么不存在呢?看来这个功能应该很有用。

解决方法

据我所知,它不存在。

您提议的 (All (a) (-> (Listof a) Integer (Option a))) 的一个问题是 (Option a) 只是 (U #f a)。也就是说,您必须用 #f 表示“无”。但是,如果您有一个 (Listof Boolean),并且 list-ref*(您的 list-ref 变体)返回 #f,您如何判断是因为索引超出范围,还是因为元素确实是 #f

解决这个问题的一种可能方法是用盒子之类的东西包装“一些”变体,并相应地调整类型。例如,

(: list-ref* (All (a) (-> (Listof a) Integer (Option (Boxof a)))))
(define (list-ref* xs i)
  (with-handlers ([exn:fail? (λ (_) #f)])
    (box (list-ref xs i))))

请注意,包装会影响性能,这可能解释了为什么它不包含在库中。