Question

I'd like to open a pseudo-tty and use the resulting slave terminal to connect to stdin/stdout on a subprocess. openPseudoTerminal gives me an IO (System.Posix.Types.Fd, System.Posix.Types.Fd), which I sought to translate into a pair of handles using fdToHandle in GHC.IO.Handle.Fd (GHC specific, but I couldn't find another such function). However, I get the following:

liftA (fdToHandle *** fdToHandle) openPseudoTerminal
Couldn't match type `System.Posix.Types.Fd'
               with `System.Posix.Internals.FD'

Any ideas how I convert between these two (presumably similar) things?

For bonus points, this will give me an IO (IO Handle, IO Handle) - is there a neat way to convert it to an IO (Handle, Handle)?

Was it helpful?

Solution

openPseudoTerminal is in the unix package, which also provides an fdToHandle with the appropriate type in System.Posix.IO.

I'll throw in the best one-liner I have come up with so far, to deal with the pair of IO Handles:

getHandles :: IO (Handle, Handle)
getHandles =
  openPseudoTerminal >>= uncurry ap . (fmap (,) . fdToHandle *** fdToHandle)

or:

getHandles =
  openPseudoTerminal >>= uncurry (ap . fmap (,)) . join (***) fdToHandle

OTHER TIPS

You can ask GHCI for information about these types --

>> :i FD
type FD = Foreign.C.Types.CInt
>> :i Fd
newtype Fd = Fd Foreign.C.Types.CInt

so they are essentially identical, except that one is a newtype and the other is a type. So the conversion functions are (I recommend choosing better names)

convert :: FD -> Fd
convert = Fd

convert' :: Fd -> FD
convert' (Fd x) = x

RE your question about converting from IO (IO Handle, IO Handle) to IO (Handle,Handle) you could do this explicitly

flatten :: IO (IO a, IO a) -> IO (a,a)
flatten x = do
  (a,b) <- x
  a'    <- a
  b'    <- b
  return (a', b')

but a better way would be to avoid creatign the IO (IO Handle, IO Handle) in the first place. Since your types are

openPseudoTerminal :: IO (Fd, Fd)
fdToHandle         :: FD -> IO Handle

you could do

getHandles :: IO (Handle, Handle)
getHandles = do
  (Fd a, Fd b) <- openPseudoTerminal
  a'           <- fdToHandle a
  b'           <- fdToHandle b
  return (a', b')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top