0

I'm newbie to Haskell and write the following small code but it failed with loop exception. The problem is the code doesn't use the loop , even recursion. That's make me crazy!

gameList :: [Int]->Int->Int->[(Int, Int)]
gameList  org pos step =
    let next  = (mod (pos + step)  2) ;
        pos = next;             
    in  [(pos, pos)]

Then save it in one file and succeed to load it into GHC with interactive mode. invoke it like this gameList [1,2,3] 0 1

It will throw error "[(*** Exception: <>"

The GHCI info :WinGHCi 1.0.6 Help me!

3
  • Infinite loop here because pos is one of your arguments. What are you trying to do? What is the expected output of gameList [1,2,3] 0 1? Commented Jan 20, 2015 at 10:50
  • 1
    BTW, you normally never need to end lines with semicolons in Haskell, nor do you need to surround definitions with parentheses. Commented Jan 20, 2015 at 11:08
  • The reason is that let expression is not assignment, it's defintion of block code. In this case, it's recursive. The same case as the following code: let t = (let pos = next; next = pos in (pos, next)) Commented Jan 21, 2015 at 2:25

2 Answers 2

4

"doesn't use a loop, even recursion"

I'm afraid it does actually use recursion, albeit in a way that isn't even possible in non-lazy languages!

The crux is that your parameter pos is never actually used anywhere, it's immediately shadowed by the pos defined in the let block (GHC would have warned you about that, with -Wall!). So your code is equivalent to

gameList org _ step =
    let next  = (mod (pos + step)  2) ;
        pos = next;             
    in  [(pos, pos)]

where next is defined in terms of pos which is defined in terms of next which is... and so on.

The obvious fix is to remove the line pos = next, which is completely unnecessary anyway.

gameList org pos step
  = let next  = (pos + step) `mod` 2
    in  [(next, next)]
Sign up to request clarification or add additional context in comments.

2 Comments

I got the reason I misunderstand the meaning of let expression. It's not a assignment, it's block of code. And also thanks your answer and suggestion on -Wall
It's a block of definitions, that's the crucial thing.
2

doesn't use the loop , even recursion

This is not correct, here's why.

gameList :: [Int]->Int->Int->[(Int, Int)]
gameList  org pos step =              -- this is an unused argument named pos
  let next  = (mod (pos + step)  2) ; -- here we define next in terms of pos
        pos = next;                   -- ... which is defined here in terms of next
    in  [(pos, pos)]                  -- here we use this circularly-defined pos

See, let is not an assignment, and it is not "executed" top-to-bottom. let introduces a block of mutually-recursive definitions. So this

let next  = (mod (pos + step)  2) ;
    pos = next;             

does not use pos the function argument at all.

1 Comment

Yes, I made that mistake because I thought let expression will just assignment ,not block of code. So It's hard for me to know why . Thanks a lot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.