Конвертировать FD в Handle
Я хотел бы открыть псевдо-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 ответа
openPseudoTerminal
находится в пакете Unix, который также обеспечивает fdToHandle
с соответствующим типом в System.Posix.IO
,
Я добавлю лучший однострочник, который я когда-либо придумал, чтобы разобраться с парой IO Handle
s:
getHandles :: IO (Handle, Handle)
getHandles =
openPseudoTerminal >>= uncurry ap . (fmap (,) . fdToHandle *** fdToHandle)
или же:
getHandles =
openPseudoTerminal >>= uncurry (ap . fmap (,)) . join (***) fdToHandle
Вы можете попросить 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')
но лучшим способом было бы избежать креатин 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')