Gaara
Gaara

Reputation: 697

Print each value in list "n" times

I am a beginner and I am trying to solve this code. Given n and a List, return a new list containing all the elements of list repeated n times. Below is my implementation

fn :: Int -> [a] -> [a]
replicate' n x = take n (repeat x)
fn n (x:xs) = case x of [] -> []
                        (_) ->  (replicate' n x) ++ fn n xs

But I am getting error saying

Couldn't match type `a' with `[t0]'
  `a' is a rigid type variable bound by
      the type signature for fn :: Int -> [a] -> [a] at temp.hs:3:1
In the pattern: []
In a case alternative: [] -> []
In the expression:
  case x of {
    [] -> []
    (_) -> (replicate' n x) ++ fn n xs }

I am not sure where the error is. Note: I am not attempting monad, any library. I am using only basic constructs Edit: I am not worried about printing as of now. I want to return the list as specified in the logic. Print can be taken care later.

Upvotes: 0

Views: 2504

Answers (4)

Adharsh M
Adharsh M

Reputation: 3832

Here's one solution with nested list comprehension.

f n arr =
    [ x | x <- arr, _ <- [1..n]]

Upvotes: 0

mb14
mb14

Reputation: 22596

Using do notation

replicate' n xs = do
      x  <- xs
      replicate n x

which can be written as

replicate' n xs = xs >>= replicate n

or

replicate' n = (>>= replicate n)

Upvotes: 1

fgv
fgv

Reputation: 835

Jeremy List's explanation directly addresses the OP's question. However, sometimes structured recursion provides a more elegant solution to problems. In this case, for example, this one liner does exactly what the OP asks:

fn :: Int -> [a] -> [a]
fn n = concat . map (replicate n)

In sum, map lifts replicate to operate in values of the list, and concat concatenates the resulting list of lists.

I hope this helps.

Upvotes: 3

Jeremy List
Jeremy List

Reputation: 1766

When you use the pattern fn n (x:xs) = ... that means x is the first element in the list and xs is the rest of the list. Your case statement is checking whether or not x is an empty list, but the pattern match ((x:xs)) already extracted it from the list. What you want is probably one of these (the compiler knows they are the same so which one you use is a matter of taste):

-- Version that uses a pattern match
fn :: Int -> [a] -> [a]
replicate' n x = take n (repeat x)
fn _ [] = []
fn n (x:xs) = (replicate' n x) ++ fn n xs

-- Version that uses a case statement
fn :: Int -> [a] -> [a]
replicate' n x = take n (repeat x)
fn n l = case l of [] -> []
                   (x:xs) ->  (replicate' n x) ++ fn n xs

This one also "fixes the error", but is probably not what you actually want:

fn :: Int -> [[a]] -> [[a]]
replicate' n x = take n (repeat x)
fn n (x:xs) = case x of [] -> []
                        (_) ->  (replicate' n x) ++ fn n xs

Upvotes: 3

Related Questions