Select a list from a 2D list, take the last item from its nearest non empty left neighbour and put it at its head
First of all, there is no need for pull's first parameter to be Maybe [[Int]]. More on that later. Also, it will get easier if we switch the parameters. Also more on that later.

So let's start with that modification:

pull  :: Int -&gt; [[Int]] -&gt; Maybe [[Int]]
pull 1 _      = Nothing
pull 2 ([]:_) = Nothing
pull _ [_]    = Nothing


As you can see, I don't use names for things I'm not interested in. This makes it possible to focus on the interesting parts, e.g. the 1 and 2 matches, and the single-element match in the last line.

Now, your other definitions get a lot easier if you don't use guards, but pattern matching instead. If we rewrote the next pattern with your style, we end up with:

pull n ([]:xs:xss) =
  | p' == Nothing = Nothing
  | otherwise     = Just ([] : p'')
  where
    p' = pull (n-1) (xs:xss)
    p''= fromJust p'


Which is slightly easier due to the missing Justs in pull (n-1) …. However, with a case … of …, it's a lot more succinct:

pull n ([]:xss) = case pull (n-1) xss of
  Nothing -&gt; Nothing
  Just p  -&gt; Just ([] : p)


This "if there is Nothing return nothing, otherwise change the Just value" slightly pattern is so common, that there is even a function for that, fmap, which you can think of as

fmap :: (a -&gt; b) -&gt; Maybe a -&gt; Maybe b
fmap _ Nothing  = Nothing
fmap f (Just v) = Just (f v)


So we can shorten that whole case to

pull n ([]:xss) = fmap ([]:) (pull (n-1) xss) -- *


We continue for the following cases:

pull 2 (xs:ys:xss) = Just ((init xs) : ((last xs):ys) : xss)
pull n (xs:[]:xss) = case pull (n-1) (xs:xss) of
  Nothing -&gt; Nothing
  Just p  -&gt; Just ((head p) : [] : (tail p))

pull n (xs:xss) = fmap (xs:) (pull (n-1) xss) -- *


Note that in both cases marked with -- *, you pattern matched on xs2:xss and used xs2:xss. That's not necessary.

So all patterns are:

pull  :: Int -&gt; [[Int]] -&gt; Maybe [[Int]]
pull 1 _           = Nothing
pull 2 ([]:_)      = Nothing
pull _ [_]         = Nothing
pull n ([]:xss)    = fmap ([]:) (pull (n-1) xss) 
pull 2 (xs:ys:xss) = Just ((init xs) : ((last xs):ys) : xss)
pull n (xs:[]:xss) = case pull (n-1) (xs:xss) of
  Nothing -&gt; Nothing
  Just p  -&gt; Just ((head p) : [] : (tail p))
pull n (xs:xss) = fmap (xs:) (pull (n-1) xss)


Now that you can see all cases, it should be obvious that your missing at least one, namely the one for the empty list pull 0 []. Also note that using last and init isn't very efficient, since you need to traverse the list twice. You could write a function like

splitLast :: [a] -&gt; ([a], a)


which returns both the init and the last element. But that's left as an exercise.

TL;DR


use case … of … (or pattern matching) instead of guards if you want to use the matched value either way (or use pattern guards).
make sure that you handle all cases
use Maybe on outputs; if your function cannot do something sensible with Maybe inputs, don't use it, that's what &gt;&gt;= is for.