Kyle Murphy orclev at gmail.com
Tue May 4 03:26:58 EDT 2010

```Alright, here's my attempt to add comments, although once again it seems
like the choice of algorithm in this example is a little wierd. By checking
the output I was able to determine that it results in True for values of
n*n-1, but why exactly that is I can't really figure out at the moment. If I
actually sat down with a sheet of paper and walked through the recursion I
might be able to make sense out of it.

--- Begin Code ---

{- This function takes an Int, and passes it to doh twice returning the
result. -}
doorOpen :: Int -> Bool
doorOpen door = doh door door

{- This function takes two Ints, returning True when the second Int is 0. If
the second Int isn't 0, it checks to see if the first Int modulus the second
Int plus one, is equal to the second Int. This condition will only be true
when the first number has the following relationship to the second one:
n*i+i. E. G. given 10 as the second number, this would be true for 10, 21,
32, 43, etc. If the condition is true it calls itself recursively while
decrementing the second Int by one, and inverting the return value. If the
condition is false it calls itself recursively while decrementing the second
Int by one, and returns the result unmodified. -}
doh :: Int -> Int -> Bool
doh door 0 = True
doh door pass =
if (door `rem` (pass+1)) == pass
then not (doh door (pass-1))
else doh door (pass-1)

{- This produces an infinite list created by calling doorOpen with the
numbers 0 to infinity -}
doors :: [Bool]
doors = [doorOpen n | n <- [0..]]

{- Utility function to print a tuple with some explanation text. Note that
this is inside the IO monad and therefore impure. -}
printDoor :: (Int,Bool) -> IO ()
printDoor (door,open) =
putStrLn ("Door #" ++ (show door) ++ " is " ++
if open then "open." else "closed.")

{- Given an Int this prints the first n elements from the doors list. This
works because zip only produces a list as long as the shortest of its two
arguments. mapM_ is a varient of map that functions on monads and that
discards its result. Ordinarily this would be pointless and might as well be
a no-op, but because printDoor executes inside the IO monad it can have side
effects from executing, and therefore must be evaluated every time. -}
printUpTo :: Int -> IO ()
printUpTo n =
mapM_ printDoor (zip [0..(n-1)] doors)

{- The main entry point to the program, calls printUpTo with 100 -}
main :: IO ()
main = printUpTo 100

--- End Code ---

-R. Kyle Murphy
--
Curiosity was framed, Ignorance killed the cat.

On Mon, May 3, 2010 at 13:15, Samuel Williams <
space.ship.traveller at gmail.com> wrote:

> Dear Kyle,
>
> I've recevied the following program. You did a fantastic job of explaining
> the other one, but as you said it wasn't a great approach, if you have a
> moment could you explain this one?
>
> doorOpen :: Int -> Bool
> doorOpen door = doh door door
>
> doh :: Int -> Int -> Bool
> doh door 0 = True
> doh door pass =
>        if (door `rem` (pass+1)) == pass
>        then not (doh door (pass-1))
>        else doh door (pass-1)
>
> doors :: [Bool]
> doors = [doorOpen n | n <- [0..]]
>
> printDoor :: (Int,Bool) -> IO ()
> printDoor (door,open) =
>        putStrLn ("Door #" ++ (show door) ++ " is " ++
>                if open then "open." else "closed.")
>
> printUpTo :: Int -> IO ()
> printUpTo n =
>        mapM_ printDoor (zip [0..(n-1)] doors)
>
> printUpTo 100
>
> Kind regards,
> Samuel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...