2013-12-16 56 views
3

我想打开伪tty,并使用生成的从终端连接到子进程上的stdin/stdout。 openPseudoTerminal给了我一个IO (System.Posix.Types.Fd, System.Posix.Types.Fd),我试图翻译成一对使用fdToHandleGHC.IO.Handle.Fd(特定于GHC,但我找不到另一个这样的功能)的句柄。但是,我得到以下内容:将FD转换为句柄

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)

回答

4

openPseudoTerminal是在Unix包,它也提供了一个fdToHandleSystem.Posix.IO适当的类型。

我会扔在最好的一个班轮我想出了到目前为止,对付对IO Handle S:

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

或:

getHandles = 
    openPseudoTerminal >>= uncurry (ap . fmap (,)) . join (***) fdToHandle 
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 

RE你的问题有关从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') 

,但更好的方法是避免creatign的首先是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') 
+0

现在我只是觉得愚蠢。谢谢! – Impredicative

+1

这两种类型都是'Num'和'Integral'的实例,因此您可以使用'fromIntegral'来回转换。 – raymonad

相关问题