我正在尝试在take
的输出上调用flatten
。问题是take
需要a
列表,但flatten
会返回Any
列表。有没有办法在它们之间进行转换?或者其他一些我应该采取的方法?我无法在Racket Docs中找到任何示例。
(: 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)
答案 0 :(得分:1)
@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*>
在您的示例中,您可以使用append*
使用flatten
。
(: 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))