Pregunta

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)?

¿Fue útil?

Solución

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

Otros consejos

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')
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top