djoloho
djoloho

Reputation: 39

Haskell do notation and pattern matching?

So here is my code..

move :: [Char] -> [Char] -> IO ()
move f t = do { putStrLn ("Moving from \"" ++ f ++ "\" to \"" ++ t ++ "\"!") }

hanoi :: Integer -> [Char] -> [Char] -> [Char] -> IO ()
hanoi 0 f _ _ = do { putStrLn ("Lane \""++ f ++ "\" empty!") }
hanoi n f h t = do { hanoi (n - 1) f t h
                   ; move f t
                   ; hanoi (n - 1) h f t } 

When I execute hanoi 4 "A" "B" "C" I expect something like this:

Moving from "A" to "B"!
Moving from "A" to "C"!
Moving from "B" to "C"!
Moving from "A" to "B"!
Moving from "C" to "A"!
Moving from "C" to "B"!
Moving from "A" to "B"!
Tower "A" empty!
...

But I am getting :

Tower "A" empty!
Moving from "A" to "B"!
Tower "C" empty!
Moving from "A" to "C"!
Tower "B" empty!
Moving from "B" to "C"!
Tower "A" empty!
Moving from "A" to "B"!
Tower "C" empty!
Moving from "C" to "A"!
Tower "B" empty!
Moving from "C" to "B"!
...

Seems to me that there is some issue with pattern matching and do notation, and I cant figure out what. Can someone explain to me what am I doing wrong or not getting here, I suppose there is someting connected with async execution of IO monad.

I am new to Haskell, and still have not entirely figured out monads...

Upvotes: 2

Views: 440

Answers (1)

Thomas M. DuBuisson
Thomas M. DuBuisson

Reputation: 64740

I don't know where your misunderstanding is, but you are probably blaming the Monad boogeyman too soon. Tracing through this program in Haskell seems identical to tracing through it's rather straight-forward C counterpart which yields the same as you showed:

// move :: [Char] -> [Char] -> IO ()
void move(char *f, char *t)
{
    // move f t = do { putStrLn ("Moving from \"" ++ f ++ "\" to \"" ++ t ++ "\"!") }
    printf("Moving from \"%s\" to \"%s\"!\n", f, t);
}

// hanoi :: Integer -> [Char] -> [Char] -> [Char] -> IO ()
void hanoi(int64_t n, char *f, char *h, char *t)
{
    if (0 == n) {
        // hanoi 0 f _ _ = do { putStrLn ("Lane \""++ f ++ "\" empty!") }
        printf("Lane \"%s\" empty!\n", f);
    } else {
        // hanoi n f h t =
        hanoi(n-1,f,t,h); // hanoi (n - 1) f t h
        move(f,t);        // move f t
        hanoi(n-1,h,f,t); // hanoi (n - 1) h f t
    }
}

int main()
{
    hanoi(4,"A","B","C");
    return 0;
}

Consider what's going on. You said hanoi 4 ... and the next line of code of any significance is hanoi (4 - 1) ... which, as @user2407038 has already commented, is going to be followed by hanoi 2, hanoi 1 and hanoi 0.

I think you should consider your algorithm more carefully.

[some problem with] pattern matching and do notation

While not entirely unrelated, these concepts are pretty distinct. The only pattern you have is 0 and you don't have any patterns due to binds in your do blocks (i.e. [some pattern] <- move).

Upvotes: 3

Related Questions