swa*_*nee 6 io haskell definition
我试图弄清楚如何IO定义基本的Haskell函数,所以我使用了这个引用,我得到了putChar函数定义:
putChar :: Char -> IO ()
putChar = primPutChar
Run Code Online (Sandbox Code Playgroud)
但是,现在我无法在primPutChar任何地方找到有关此功能的更多信息.也许它可能是指一个预编译的函数,可以作为共享对象的二进制文件?如果是这种情况,是否可以查看其源代码?
Zet*_*eta 10
prim*意思既然您在报告中提出这个问题,我们也会根据报告回答这个问题:
在Haskell中无法定义的基元,以"
prim" 开头的名称表示,在模块中以系统相关的方式定义,PreludeBuiltin此处未显示
顺便提一下,这在Haskell2010中仍然是相同的.
但是,您可以查看base源代码,了解它在GHC中的实现方式:
putChar :: Char -> IO ()
putChar c = hPutChar stdout c
Run Code Online (Sandbox Code Playgroud)
从那里你将深入兔子洞.怎么hPutChar知道如何打印东西?嗯,事实并非如此.它只"缓冲"并检查你可以写:
hPutChar :: Handle -> Char -> IO ()
hPutChar handle c = do
c `seq` return ()
wantWritableHandle "hPutChar" handle $ \ handle_ -> do
hPutcBuffered handle_ c
Run Code Online (Sandbox Code Playgroud)
写入完成后writeCharBuffer,填充内部缓冲区直到其满(或已达到一行 - 实际上取决于缓冲模式):
writeCharBuffer h_@Handle__{..} !cbuf = do
-- much code omitted, like buffering
bbuf'' <- Buffered.flushWriteBuffer haDevice bbuf'
-- more code omitted, like buffering
Run Code Online (Sandbox Code Playgroud)
那么flushWriteBuffer定义在哪里?它实际上是以下部分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
Run Code Online (Sandbox Code Playgroud)
文件描述符(FD)是以下的实例BufferedIO:
instance BufferedIO FD where
-- some code omitted
flushWriteBuffer fd buf = writeBuf' fd buf
Run Code Online (Sandbox Code Playgroud)
并writeBuf使用instance GHC.IO.Device.RawIO FD'swrite,最终导致:
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
Run Code Online (Sandbox Code Playgroud)
所以,putChar用途write.至少在GHC实施中.但是,该报告不需要该实现,因此允许另一个编译器/运行时用户使用其他功能.
GHC的实现使用write内部缓冲区来编写内容,包括单个字符.