Reputation: 697
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
Reputation: 3832
Here's one solution with nested list comprehension.
f n arr =
[ x | x <- arr, _ <- [1..n]]
Upvotes: 0
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
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
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