Q:

Difficulty getting desired output file type in function

After going through a couple of chapters of "Learn You A Haskell", I wanted to write something hands on and decided to implement a Sudoku solver. I am trying to implement the B2 function from here: http://www.cse.chalmers.se/edu/year/2013/course/TDA555/lab3.html
Here's my code:
data Sudoku = Sudoku { getSudoku :: [[Maybe Int]] } deriving (Show, Eq)

printSudoku :: Sudoku -> IO ()
printSudoku s = do
putStrLn .  unlines .  map (map (maybe '.' ( head .  show))) $ rows s

stringToSudoku :: String -> [[Maybe Int]]
stringToSudoku [] = []
stringToSudoku s = (f x):stringToSudoku y
    where (x,y) = splitAt 9 s
        f = map (\x -> if (digitToInt x)==0 then Nothing else Just (digitToInt x))

readSudoku :: FilePath -> IO Sudoku
readSudoku path = do
    handle <- openFile path ReadMode
    contents <- hGetContents handle
    return $ Sudoku $ stringToSudoku contents

I am able to get the desired output:
readSudoku "sudoku.txt" >>= printSudoku 
.......1. 
4........
.2.......
....5.4.7
..8...3..
..1.9....
3..4..2..
.5.1.....
...8.6...

However, I had to convert [[Maybe Int]] to Sudoku in the readSudoku function.  It should be possible to do this in the stringToSudoku function right? 
The sudoku.txt file contains 1 line
    000000010400000000020000000000050407008000300001090000300400200050100000000806000

A:

If you want stringToSudoku to return Sudoku you could do:
stringToSudoku :: String -> Sudoku
stringToSudoku s = Sudoku $ stringToGrid s
    where stringToGrid [] = []
          stringToGrid s = let (x, y) = splitAt 9 s
                               f = map (\x -> if (digitToInt x)==0 then Nothing else Just (digitToInt x))
                           in (f x):stringToGrid y

