"Sequence full of colors" challenge on HackerRank
step does two things: (1) step to the next state, and (2) check that the state is valid. Its name suggests only the first meaning. The repetition of wrapValidInJust suggests that they can be separated.

Instead of == you can use pattern-matching.


isgood :: String -&gt; Bool
isgood = isValidFinal . foldM (check . step) (0, 0)
  where

    step (x, y) 'R' = (x-1, y)
    step (x, y) 'G' = (x+1, y)
    step (x, y) 'Y' = (x, y-1)
    step (x, y) 'B' = (x, y+1)

    check (x, y) = if abs x &lt;= 1 &amp;&amp; abs y &lt;= 1 then Just (x, y) else Nothing

    ...

Another reason step is hard to read is that you need to keep track of differences, which complexifies the meaning of x and y. You can just as easily count the four colors independently and compute the difference only in check. This is also the opportunity to use a record or a map to make the update syntax more uniform:
data RGBY = RGBY { r, g, b, y :: Int }

isgood :: String -&gt; Bool
isgood = isValidFinal . foldM (check . step) (RGBY 0 0 0 0)
  where

    step x 'R' = x { r = r x + 1 }
    step x 'G' = x { g = g x + 1 }
    step x 'Y' = x { y = y x + 1 }
    step x 'B' = x { b = b x + 1 }

    check x = if abs (r x - g x) &lt;= 1 &amp;&amp; abs (y x - b x) &lt;= 1
      then Just (x, y) else Nothing

    ...