我想打开一个伪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)
?
答案 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')