The problem is straightforward if approached from the right direction. As a first approximation, you can define your function as a left fold over the input list:
fun :: Eq a => a -> [[a]] -> [[a]]
fun z xss = newList
where (foundZ, newList, _) = foldl ... (False, [], False) xss
Note that the fold will return two values, namely the resulting list and a boolean indicating if a 1 (or in this case, the parameter z) is found in the list. The third parameter indicates if a list has already been replaced (we only want to do one replacement). If we are clever (and we will be) we can use the value of foundZ inside the body of the function passed to foldl - that is, we can use it before it has apparently been computed. All that is left is to write the argument function to foldl:
\(fn,xss',rpl) xs ->
case xs of
...
Consider the different possibilities for xs: it is the empty list, it is the list containing a z as its head, and every other list:
[] | not rpl -> ...
(x:r) | x == z && not fn -> ...
_ -> (fn, xs:xss',rpl)
Note that when we check for x == z we also check not fn because we only want to take a single z from a single list, so if we already found one, we do not want to do that again. In the case for the empty list, we check for not rpl for the same reason. The last case is obvious, but the first two may not be.
[] | not rpl -> (fn, (if foundZ then [z] else []):xss', True)
The case for the empty list simple checks if the z was found - if so, it returns a singleton list containing that z.
(x:r) | x == z && not fn -> (True , r:xss', rpl)
The case for the list starting with a z returns True for found and prepends the tail of that list to the result (this is how the 1 gets removed).
Put it all together and you get a simple function:
fun :: Eq a => a -> [[a]] -> [[a]]
fun z xss = reverse newList
where (foundZ, newList, _) =
foldl
(\(fn,xss',rpl) xs ->
case xs of
[] | not rpl -> (fn, (if foundZ then [z] else []):xss', True)
(x:r) | x == z && not fn -> (True , r:xss', rpl)
_ -> (fn, xs:xss', rpl)
) (False, [], False) xss
and
>fun 1 [[2,1,3,1],[],[2,3],[1,2,3],[4]]
[[2,1,3,1],[1],[2,3],[2,3],[4]]
>fun 1 [[1,2,1,3,1],[],[2,3],[1,2,3],[4]]
[[2,1,3,1],[1],[2,3],[1,2,3],[4]]
1in the head? Leave the empty list empty?1, do you want to check only lists after the current empty list or they may be wherever in the list of lists, even before the current empty list?a = [[1,3,1],[],[2,3],[9,1,2,3],[4]]and would givea = [[3,1],[1],[2,3],[9,1,2,3],[4]]mapmight not be the best approach here since you're not uniformly applying a function to all elements. Perhaps, an explicit recursion fits better. Also, I think you want to have these two actions happen both or none at all. So the number of total numbers stay invariant.