将FD转换为句柄

时间:2013-12-16 14:18:01

标签: linux haskell tty

我想打开一个伪tty并使用生成的从属终端连接到子进程上的stdin / stdout。 openPseudoTerminal给了我一个IO (System.Posix.Types.Fd, System.Posix.Types.Fd),我试图在fdToHandle中使用GHC.IO.Handle.Fd转换为一对句柄(具体GHC,但我找不到另一个这样的函数) 。但是,我得到以下内容:

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

我是如何在这两种(可能是相似的)事物之间进行转换的?

对于奖励积分,这会给我一个IO (IO Handle, IO Handle) - 是否有一种巧妙的方式将其转换为IO (Handle, Handle)

2 个答案:

答案 0 :(得分:4)

openPseudoTerminal位于unix包中,它还在fdToHandle中提供了System.Posix.IO具有相应类型的内容。

我会抛出迄今为止我提出的最好的单线,以处理IO Handle对{

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

或:

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

答案 1 :(得分:2)

您可以向GHCI咨询有关这些类型的信息 -

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

因此它们基本相同,只是一个是newtype而另一个是type。所以转换函数是(我建议选择更好的名字)

convert :: FD -> Fd
convert = Fd

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

重新提问您有关从IO (IO Handle, IO Handle)转换为IO (Handle,Handle)的问题,您可以明确地执行此操作

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

但更好的方法是首先避免创造IO (IO Handle, IO Handle)。由于你的类型是

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

你可以做到

getHandles :: IO (Handle, Handle)
getHandles = do
  (Fd a, Fd b) <- openPseudoTerminal
  a'           <- fdToHandle a
  b'           <- fdToHandle b
  return (a', b')