2013-12-16 55 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

相關問題