Haskell primPutChar 定义
Haskell primPutChar definition
我试图弄清楚基本的 IO
Haskell 函数是如何定义的,所以我使用了 this reference 并且得到了 putChar
函数定义:
putChar :: Char -> IO ()
putChar = primPutChar
但是,现在我无法在任何地方找到有关此 primPutChar
函数的更多信息。也许它可能指的是一个预编译函数,可以从共享对象中以二进制形式使用?如果是这样的话,是否可以查看其源代码?
prim*
是什么意思
既然你是从报告的角度问这个问题,那我们也从报告的角度来回答这个问题:
Primitives that are not definable in Haskell , indicated by names starting with "prim
", are defined in a system dependent manner in module PreludeBuiltin
and are not shown here
这在Haskell2010 by the way中仍然是一样的。
它是如何在 GHC 中实现的
但是,您可以have a look at base
's source查看它在 GHC 中的实现方式:
putChar :: Char -> IO ()
putChar c = hPutChar stdout c
从那里你将深入兔子洞。 hPutChar
怎么知道如何打印东西?好吧,事实并非如此。它只 "buffers" 并检查你是否可以写:
hPutChar :: Handle -> Char -> IO ()
hPutChar handle c = do
c `seq` return ()
wantWritableHandle "hPutChar" handle $ \ handle_ -> do
hPutcBuffered handle_ c
写入是在writeCharBuffer
中完成的,它会填充一个内部缓冲区直到它满了(或者已经达到一行——这实际上取决于缓冲区模式):
writeCharBuffer h_@Handle__{..} !cbuf = do
-- much code omitted, like buffering
bbuf'' <- Buffered.flushWriteBuffer haDevice bbuf'
-- more code omitted, like buffering
所以flushWriteBuffer
defined? It's actually part of stdout
在哪里:
stdout :: Handle
stdout = unsafePerformIO $ do
setBinaryMode FD.stdout
enc <- getLocaleEncoding
mkHandle FD.stdout "<stdout>" WriteHandle True (Just enc)
nativeNewlineMode{-translate newlines-}
(Just stdHandleFinalizer) Nothing
stdout :: FD
stdout = stdFD 1
文件描述符 (FD
) 是 BufferedIO
的一个实例:
instance BufferedIO FD where
-- some code omitted
flushWriteBuffer fd buf = writeBuf' fd buf
和writeBuf
使用instance GHC.IO.Device.RawIO FD
's write
, and that ultimately leads to:
writeRawBufferPtr loc !fd buf off len
| isNonBlocking fd = unsafe_write -- unsafe is ok, it can't block
| otherwise = do r <- unsafe_fdReady (fdFD fd) 1 0 0
if r /= 0
then write
else do threadWaitWrite (fromIntegral (fdFD fd)); write
where
do_write call = fromIntegral `fmap`
throwErrnoIfMinus1RetryMayBlock loc call
(threadWaitWrite (fromIntegral (fdFD fd)))
write = if threaded then safe_write else unsafe_write
unsafe_write = do_write (c_write (fdFD fd) (buf `plusPtr` off) len)
safe_write = do_write (c_safe_write (fdFD fd) (buf `plusPtr` off) len)
我们可以看到 c_safe_write
和 c_write
,它们通常绑定到 C 库函数:
foreign import capi unsafe "HsBase.h write"
c_write :: CInt -> Ptr Word8 -> CSize -> IO CSsize
因此,putChar
使用 write
。至少在 GHC 的实施中。然而,该报告并不要求实施,因此允许另一个 compiler/runtime 使用其他功能。
TL;DR
GHC 的实现使用 write
和内部缓冲区来写入内容,包括单个字符。
我试图弄清楚基本的 IO
Haskell 函数是如何定义的,所以我使用了 this reference 并且得到了 putChar
函数定义:
putChar :: Char -> IO ()
putChar = primPutChar
但是,现在我无法在任何地方找到有关此 primPutChar
函数的更多信息。也许它可能指的是一个预编译函数,可以从共享对象中以二进制形式使用?如果是这样的话,是否可以查看其源代码?
prim*
是什么意思
既然你是从报告的角度问这个问题,那我们也从报告的角度来回答这个问题:
Primitives that are not definable in Haskell , indicated by names starting with "
prim
", are defined in a system dependent manner in modulePreludeBuiltin
and are not shown here
这在Haskell2010 by the way中仍然是一样的。
它是如何在 GHC 中实现的
但是,您可以have a look at base
's source查看它在 GHC 中的实现方式:
putChar :: Char -> IO ()
putChar c = hPutChar stdout c
从那里你将深入兔子洞。 hPutChar
怎么知道如何打印东西?好吧,事实并非如此。它只 "buffers" 并检查你是否可以写:
hPutChar :: Handle -> Char -> IO ()
hPutChar handle c = do
c `seq` return ()
wantWritableHandle "hPutChar" handle $ \ handle_ -> do
hPutcBuffered handle_ c
写入是在writeCharBuffer
中完成的,它会填充一个内部缓冲区直到它满了(或者已经达到一行——这实际上取决于缓冲区模式):
writeCharBuffer h_@Handle__{..} !cbuf = do
-- much code omitted, like buffering
bbuf'' <- Buffered.flushWriteBuffer haDevice bbuf'
-- more code omitted, like buffering
所以flushWriteBuffer
defined? It's actually part of stdout
在哪里:
stdout :: Handle stdout = unsafePerformIO $ do setBinaryMode FD.stdout enc <- getLocaleEncoding mkHandle FD.stdout "<stdout>" WriteHandle True (Just enc) nativeNewlineMode{-translate newlines-} (Just stdHandleFinalizer) Nothing
stdout :: FD
stdout = stdFD 1
文件描述符 (FD
) 是 BufferedIO
的一个实例:
instance BufferedIO FD where
-- some code omitted
flushWriteBuffer fd buf = writeBuf' fd buf
和writeBuf
使用instance GHC.IO.Device.RawIO FD
's write
, and that ultimately leads to:
writeRawBufferPtr loc !fd buf off len | isNonBlocking fd = unsafe_write -- unsafe is ok, it can't block | otherwise = do r <- unsafe_fdReady (fdFD fd) 1 0 0 if r /= 0 then write else do threadWaitWrite (fromIntegral (fdFD fd)); write where do_write call = fromIntegral `fmap` throwErrnoIfMinus1RetryMayBlock loc call (threadWaitWrite (fromIntegral (fdFD fd))) write = if threaded then safe_write else unsafe_write unsafe_write = do_write (c_write (fdFD fd) (buf `plusPtr` off) len) safe_write = do_write (c_safe_write (fdFD fd) (buf `plusPtr` off) len)
我们可以看到 c_safe_write
和 c_write
,它们通常绑定到 C 库函数:
foreign import capi unsafe "HsBase.h write"
c_write :: CInt -> Ptr Word8 -> CSize -> IO CSsize
因此,putChar
使用 write
。至少在 GHC 的实施中。然而,该报告并不要求实施,因此允许另一个 compiler/runtime 使用其他功能。
TL;DR
GHC 的实现使用 write
和内部缓冲区来写入内容,包括单个字符。