Typed Racket 将 Any 转换为 All (a)

Typed Racket convert Any to All (a)

我正尝试在 flatten 的输出上调用 take。问题是 take 需要 a 的列表,但 flatten returns 需要 Any 的列表。有没有办法在它们之间进行转换?或者我应该采取的其他方法?我无法在球拍文档中找到任何示例。

(: extend (All (a) (-> (Listof a) Integer (Listof a))))               
(define (extend l n)                                 
  ; extend a list to length 'n' by appending it to itself           
  ;                                                        
  ; @l        list of any                                         
  ; @n        int                                              
  ; @return   list of any 

  (take (flatten (make-list n l)) n)) 

来自解释器,这里是每个函数的确切类型以供参考。

 > take                
 - : (All (a) (-> (Listof a) Integer (Listof a)))       
 #<procedure:take> 

 > flatten             
 - : (-> Any (Listof Any))
 #<procedure:flatten>

这里也是错误提示,供参考。

alg/waterfall.rkt:65:2: Type Checker: Polymorphic function `take' could not be applied to arguments:                                                                         
Argument 1:                                                                 
  Expected: (Listof a)                                                      
  Given:    (Listof Any)                                                    
Argument 2:                                                                 
  Expected: Integer                                                         
  Given:    Integer                                                         

Result type:     (Listof a)                                                 
Expected result: (Listof a)  

@Alexis King 是对的。 flatten 函数具有更复杂的行为,不适合您需要的类型。 append*函数更简单,这里其实就是你需要的,而不是flatten.

在你使用的地方:

; n : Integer
; l : (Listof a)
(take (flatten (make-list n l)) n)
; expected type: (Listof a)

flatten 的输入是 (Listof (Listof a)),要进行类型检查,输出必须是 (Listof a)。这必须是真实的 *即使 a 包含列表*.

你想要的函数是 (Listof (Listof a)) -> (Listof a) 类型的东西。现在,flatten 总是有那个类型吗?不,它不能,这是一个反例:

a = (Listof Integer)
input : (Listof (Listof (Listof Integer)))
input = (list (list (list 1)))
expected output type: (Listof (Listof Integer))
actual output value:  (list 1)

因此 flatten 不能有类型 (Listof (Listof a)) -> (Listof a)。你需要的是append*,它确实有那个类型。

> append*
- : (All (a) (-> (Listof (Listof a)) (Listof a)))
#<procedure:append*>

在您的示例中,您可以在使用 flatten 的地方使用 append*

(: extend (All (a) (-> (Listof a) Integer (Listof a))))               
(define (extend l n)                                 
  ; extend a list to length 'n' by appending it to itself           
  ;                                                        
  ; @l        list of any                                         
  ; @n        int                                              
  ; @return   list of any 

  (take (append* (make-list n l)) n))