2
votes

I want to write a Haskell program that replicates the elements of a list a given number of times. Here's my code:

repli :: [a] -> a -> [a]
repli xs n = foldl1 (\x -> take n (repeat x)) xs

My problem is I get the following errors when compiling:

'take' is applied to too many arguments

couldn't match expected type '[a]->[a]' with actual type '[[a]]'

5
From your code, it seems that you want repli [1,2] 2 to generate [1,1,2,2], and not [1,2,1,2]. Is that right? Please clarify this in your question, since answers below sometimes chose the second interpretation.chi

5 Answers

9
votes

The type signature for foldl1 is:

foldl1 :: (a -> a -> a) -> [a] -> a

Hence, the first argument needs to be a function of two arguments. The lambda expression you're passing only takes one argument. You probably meant to do something like this:

repli :: [a] -> Int -> [a]
repli xs n = concat $ map (\x -> take n (repeat x)) xs

Or, to do it better, you can use the replicate function:

repli :: [a] -> Int -> [a]
repli xs n = concat $ map (replicate n) xs

Or, to do it even betterer, you can use the [] monad:

repli :: [a] -> Int -> [a]
repli xs n = xs >>= replicate n
3
votes

How about this very simple line:

repli ::  [a] -> Int -> [a]
repli xs n = concat (replicate n xs)
0
votes

Consider Prelude replicate before rolling out your own function: http://zvon.org/other/haskell/Outputprelude/replicate_f.html

repli xs n = foldr (++) [] (replicate n xs)
0
votes

you can use "take" and "repeat". You also need to provide a base case where the list is empty.

repli [] _ = []
repli (x:xs) y = take y (repeat x) ++ repli xs y 
0
votes

A simple solution that worked for me

f :: Int -> [Int] -> [Int]
f n arr = concatMap (\num -> replicate n num) arr