当前位置:  开发笔记 > 前端 > 正文

Haskell primPutChar定义

如何解决《HaskellprimPutChar定义》经验,为你挑选了1个好方法。

我试图弄清楚如何IO定义基本的Haskell函数,所以我使用了这个引用,我得到了putChar函数定义:

putChar    :: Char -> IO ()
putChar    =  primPutChar

但是,现在我无法在primPutChar任何地方找到有关此功能的更多信息.也许它可能是指一个预编译的函数,可以作为共享对象的二进制文件?如果是这种情况,是否可以查看其源代码?



1> Zeta..:

什么prim*意思

既然您在报告中提出这个问题,我们也会根据报告回答这个问题:

在Haskell中无法定义的基元,以" prim" 开头的名称表示,在模块中以系统相关的方式定义,PreludeBuiltin此处未显示

顺便提一下,这在Haskell2010中仍然是相同的.

它是如何在GHC中实施的

但是,您可以查看base源代码,了解它在GHC中的实现方式:

putChar         :: Char -> IO ()
putChar c       =  hPutChar stdout c

从那里你将深入兔子洞.怎么hPutChar知道如何打印东西?嗯,事实并非如此.它只"缓冲"并检查你可以写:

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定义在哪里?它实际上是以下部分stdout:

stdout :: Handle
stdout = unsafePerformIO $ do
   setBinaryMode FD.stdout
   enc <- getLocaleEncoding
   mkHandle FD.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'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_writec_write,这通常是绑定C库函数:

foreign import capi unsafe "HsBase.h write"
   c_write :: CInt -> Ptr Word8 -> CSize -> IO CSsize

所以,putChar用途write.至少在GHC实施中.但是,该报告不需要该实现,因此允许另一个编译器/运行时用户使用其他功能.

TL; DR

GHC的实现使用write内部缓冲区来编写内容,包括单个字符.



推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有