It looks to me like you aren't actually drawing anything there. Are you sure setColors does what you think it does? If memory serves me, it's for setting the color palette for an 8-bit surface, whereas you're explicitly setting a 32-bit video mode.
As an aside, if you've done graphics programming before I'm sure you know the difference, but for the benefit of others reading this: 8-bit video modes store pixel colors as an 8-bit index into a table of 256 colors chosen from a much larger set of potential colors; in higher color depths, the palette table is dispensed with and each pixel color is stored directly as a packed RGB triple, typically of 8 bits each (32-bit pixels either have an 8-bit alpha channel as well, or just 8 bits of padding for better memory alignment, I can't recall).
Either way, if I'm guessing correctly what you were attempting to do, try adding this to your program:
import Ix
-- Given coordinates, create a 1x1 rectangle containing that pixel
getPix x y = SDL.Rect (fromIntegral x) (fromIntegral y) 1 1
-- Draw a pixel on a surface with color determined by position
drawPixel surf (x, y) = do
let pixRect = Just (getPix x y)
pixColor <- createColor surf x y 255
SDL.fillRect surf pixRect pixColor
-- Apply drawPixel to each coordinate on the screen
drawGrad screen = mapM_ (drawPixel screen) $ range ((0,0),(255,255))
Warning: That's almost certainly horrible and inefficient code, and it has been tested only in a Win32 environment. I am not a qualified Haskell programmer and my advice should not be taken as indicative of correct use of the language. For external use only. Do not taunt the Happy Fun IO Monad.
Either way, I think your problem lies with use of SDL, not Haskell. Graphics.UI.SDL is pretty raw, little more than wrapping the C API in appropriate Haskell types. If you've not used SDL before, or used it only with slightly more elaborate bindings (e.g., PyGame), you may want to consider looking for SDL examples in C as reference material.