4

If have problems understanding why the code below doesn't stop when I run it on repl.it.

-- The second argument is meant to be an infinite ascending list, don't bother yourself with any other case
isin :: Int -> [Int] -> (Bool, [Int])
isin n []       = (False, []) -- This case is unnecessary because the list is infinite, but just for completion
isin n l@(x:xs) =
  case n `compare` x of
    LT -> (False, l)
    EQ -> (True, xs)
    GT -> isin n xs

>>> isin 2 [1..]
-- prints nothing              --Edit
-- expected (True, [3,4,5...   --Edit

In my mind, the execution of this should be shomething like:

-- underscore is meant to be "unevaluated". (Probably not 100% accurate but you can follow my idea)

isin 2 1:_      -- first call 
  2 `compare` 1 -- GT
  isin 2 _

isin 2 2:_      -- second call
  2 `compare` 2 -- EQ
  (True, _)

(True, 3:_)     -- returned result

AFAIK, this should work properly, unless tuples are strict, in which case i'll use a different structure... but I'm 90% sure they are not

In case you wonder, the idea is that isin will be call multiple times with increasing numbers over the same list, so I can drop heads while checking.

lsmor
  • 4,698
  • 17
  • 38
  • 3
    Can't reproduce. When I run that, I get `(True,[3,4,5,6,7...` – Joseph Sible-Reinstate Monica Apr 23 '20 at 16:37
  • 2
    Wait. Are you mixing up "infinitely long output" with "runs forever"? They're not the same thing. – Joseph Sible-Reinstate Monica Apr 23 '20 at 16:39
  • 7
    Tuples are not strict, but printing is. When you type the expression into ghci, you are asking ghci to print it. In order to print a pair, ghci has to first print the left component (easy and short), and then to print the right component (also easy, but very long...). Try to print just the left component, or just the first 10 elements of the right component, to see whether you get back the ghci prompt. – jpmarinier Apr 23 '20 at 16:43
  • 3
    If you call `fst (isin 2 [1..])` it will terminate. The problem is that the second value of the tuple is an infinite list, so it can't ever fully print that second part. It will run forever. – 4castle Apr 23 '20 at 16:45
  • Oh!... what a silly mistake. You're right – lsmor Apr 23 '20 at 18:54
  • @JosephSible-ReinstateMonica I was expecting your output actually. But I get nothing instead. That's why I thought it was running forever. Do you know if it is a ghci option? – lsmor Apr 23 '20 at 19:00
  • @lsmor That's really weird and shouldn't happen. Do you have anything in your `.ghci`? – Joseph Sible-Reinstate Monica Apr 23 '20 at 19:02
  • 2
    @JosephSible-ReinstateMonica actually I was using an online repl: https://repl.it/languages/haskell in order to show to a workmate. So I don't know about its config – lsmor Apr 23 '20 at 19:04

1 Answers1

8

You're seeing an artifact of repl.it. In GHCi on your computer, this would behave as you'd expect. In particular, repl.it doesn't seem to send you any output until all of the output has been generated. Here's two examples that will demonstrate this:

import Control.Concurrent
mapM_ (\i -> threadDelay 1000000 *> print i) [1..10]

If you run that on repl.it, nothing will happen for 10 seconds, then you'll suddenly get back all 10 numbers. If you run it on GHCi on your computer, then you'll get one number per second for 10 seconds.

[0..]

If you run that on repl.it, it'll never return anything. If you run it on GHCi on your computer, you'll get a neverending stream of all of the natural numbers.

Interestingly, this only seems to happen for code you run from the console/terminal (right side). If you put all your code in a file (left side) and use the run button, then it works the same as running locally would.

I posted about this at https://repl.it/bugs/p/consoleterminal-doesnt-show-output-until-the-end - we'll see what they say.

  • Thank's I've edit the fact that I was expecting `(True, [1,2,3...)` instead of nothing. So It is clearer what I meant when saying "runs forever" – lsmor Apr 23 '20 at 19:30