I'm trying to call take
on the output of flatten
. The problem is that take
requires a list of a
but flatten
returns a list of Any
. Is there a way to convert between them? Or some other approach I'm supposed to take? I wasn't able to find any examples in the 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))
From the interpreter, here are the exact types for each function for reference.
> take
- : (All (a) (-> (Listof a) Integer (Listof a)))
#<procedure:take>
> flatten
- : (-> Any (Listof Any))
#<procedure:flatten>
Here's the error message for reference too.
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 is right. The
flatten
function has more complicated behavior that doesn't fit with the type you need. Theappend*
function is simpler, and here it's actually what you need instead offlatten
.In the place where you use it:
The input to
flatten
is a(Listof (Listof a))
, and for it to typecheck the output must be a(Listof a)
. This has to be true *even whena
includes lists*.The function you want is something with the type
(Listof (Listof a)) -> (Listof a)
. Now, doesflatten
always have that type? No it can't, here's a counterexample:Therefore
flatten
cannot have the type(Listof (Listof a)) -> (Listof a)
. What you need isappend*
, which does have that type.In your example, you can use
append*
where you usedflatten
.