Archive for November, 2011

Haskell Trail for Sudoku

November 4, 2011

I’m going to document my “experiments” of learning Haskell, in the process of trying to write a Sudoku program — I know, I know, everyone does.  It’s not that I know more, or better, but as an educational path.

I need to specify up front that much of the code that follows is not intended as good examples, but it is what I’ve written; in fact, some of it will be decidedly bad, but I’m being more honest, and trying to learn.  If you, my friend, find a place where I’m off, wrong, and things are missing, please let me know.

Here, for example, is a “wasted” function

rdLines handle =
   Prelude.catch (
        do
            ln <- hGetLine handle
            rest <- rdLines handle
            -- this can't be the best way to accomplish that !!
            return (ln : rest) )
       (\e -> if isEOFError e then return [] else ioError e)

What I wanted, even though I am on the wrong path, is “return ln : rdLines handle” in the proper syntax.

Here’s my main function, so far:

{-
    given a filename, read the Sudoku board therein
    the format is: one line of the n "symbols" -- where n = s^2 for some integer s
    then n lines of n characters each
    return a board as defined above
 -}
doRead filename =
    bracket (openFile filename ReadMode) hClose
        (\h -> do
            syms <- hGetLine h
            putStrLn ("The first line length (of symbols) is " ++ (show (length syms)))
            let size = sqrtInt (length syms) in do
                lns <- rdLines h
                return (B syms (toInteger size) lns))

The nice function, giving the main structure, is bracket, which takes a first function, passing the result to the third function; and the second function is invoked whether the last succeeded or not, when it is finished.

So we open a file,  passing the result of that function (a handle) to the third function, hGetLine, debug that, the sqrtInt func. is my own creation, below, then read the remaining lines.  Better would be:

doRead filename =
    bracket (openFile filename ReadMode) hClose
        (\h -> do
            syms <- hGetLine h
            putStrLn ("The first line length (of symbols) is " ++ (show (length syms)))
            let size = sqrtInt (length syms) in do
                lns <- hGetContents h
                return (B syms (toInteger size) (lines lns)))

Cleaner, no?  That came to me in my sleep; I thought about what it is I am trying to accomplish, rather than how to do it, which was distracting me yesterday.

-- this is way too much work for that
sqrtInt i = floor (sqrtFloat (1.0 * (fromIntegral i)))

Is this really all necessary to calculate the integer (Int, if you want to be technical) square root of an integer [Int]?

I do hope some Haskell hacker, or more than one, reads this — some “help” would be nice learning; and something beyond LYaHGG [Learn You a Haskell Great Good]; that and a few others are good resources, like Real World Haskell, and probably YAHT.

What I learned from yesterday/today: Haskell is not well learned while I’m over-tired; I can’t think straight, and this more than anything else requires straight, rigorous thinking!

Advertisements