Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell IO - hGetContents: illegal operation (handle is closed)

Tags:

haskell

I'm trying to comprehend haskell IO but this feature of stdin ultimately confuses me: When I try to use some function like getContents, for example in:

let main = do x<-getContents; putStrLn x

I get the following error:

hGetContents: illegal operation (handle is closed)

How I am supposed to do any IO with this? Is there some fix, or should I look up for another analogical IO function?

like image 766
Jakub Bartczuk Avatar asked Aug 10 '13 10:08

Jakub Bartczuk


Video Answer


3 Answers

getContents == hGetContents stdin. In fact hGetContents marks its handle (semi-)closed and this means anything attempting to read from stdin ever again will fail.

Take a look at After using getContents in the Haskell User Guide

like image 172
Oscerd Avatar answered Oct 10 '22 22:10

Oscerd


I'd suggest you to also investigate an alternative approach. There some inherent problems with getContents and similar operations:

  1. You can have an invalid handle - a handle that is already closed. This is common in most languages, but we can do better. Ideally, we'd like to be sure that once we close a handle, we can't use it further.
  2. getContents is a lazy IO, which means (among other problems) that:
    • We have little or no control of when (if) the handle is closed.
    • While we're processing the string returned by getContents, the data are read using lazy IO operations. This means that inside pure computations we can get IO effects and errors.

A safer alternative is to use another concept, called iteratees, conduits or pipes. The idea is that you describe your components as things that read some input data and/or write output and then combine them together. This allows you to write very robust and elegant code.

like image 35
Petr Avatar answered Oct 10 '22 22:10

Petr


This does not reproduce in normal operation

If you try to use getContents from within ghci, as you seem to be doing, that's exactly what will happen when you use it the second time around. The first invocation will set the handle in the (semi)closed state, and all subsequent attempts to use it will fail.

like image 5
n. 1.8e9-where's-my-share m. Avatar answered Oct 10 '22 20:10

n. 1.8e9-where's-my-share m.