Haskell-primPutChar定义
我试图弄清楚基本的Haskell-primPutChar定义,haskell,io,definition,Haskell,Io,Definition,我试图弄清楚基本的IOHaskell函数是如何定义的,所以我使用了putChar函数定义: putChar :: Char -> IO () putChar = primPutChar 但是现在,我在任何地方都找不到关于这个primPutChar函数的更多信息。也许它是指一个预编译的函数,从共享对象中以二进制形式提供?如果是这样的话,有可能看到它的源代码吗?什么是prim*意思 既然你是从报告的角度问这个问题,那么让我们也从报告的角度回答这个问题: 在Haskell中无法定
IO
Haskell函数是如何定义的,所以我使用了putChar
函数定义:
putChar :: Char -> IO ()
putChar = primPutChar
但是现在,我在任何地方都找不到关于这个primPutChar
函数的更多信息。也许它是指一个预编译的函数,从共享对象中以二进制形式提供?如果是这样的话,有可能看到它的源代码吗?什么是prim*
意思
既然你是从报告的角度问这个问题,那么让我们也从报告的角度回答这个问题:
在Haskell中无法定义的原语(以“prim
”开头的名称表示)在模块PreludeBuiltin
中以系统相关的方式定义,此处未显示
这在中国仍然是一样的
它在GHC中的实现方式
但是,您可以查看它在GHC中的实现方式:
putChar :: Char -> IO ()
putChar c = hPutChar stdout c
从那里你将深入兔子洞。你怎么知道怎么打印东西?嗯,没有。它仅“缓冲”并检查您是否可以写入:
hPutChar :: Handle -> Char -> IO ()
hPutChar handle c = do
c `seq` return ()
wantWritableHandle "hPutChar" handle $ \ handle_ -> do
hPutcBuffered handle_ c
写入是在填充内部缓冲区直到其满(或到达一行,实际上取决于缓冲区模式)的过程中完成的:
文件描述符(FD
)是以下内容的实例:
和writeBuf
使用,最终:
因此,putChar
使用。至少在GHC的实施中。但是,报告不需要该实现,因此允许另一个编译器/运行时使用其他函数
TL;博士
GHC的实现使用内部缓冲区来写东西,包括单个字符。函数名以
prim
开头意味着它是一个内置原语。这种函数的定义不能用Haskell来给出;目标平台之间也会有所不同。有时它是一个外部函数,有时它是编译器熟知的函数名(这样它可以在调用函数的地方直接发出适当的代码)。@Andreychernayakhovskiy将您的答案作为答案,而不是注释。您可以在基本包中看到它:由于最新的haddock,您可以非常轻松地导航它@西比:谢谢,真有趣!然而,为什么在那个地方,putChar
是用Haskell代码定义的,而在onlinereport中,他们暗示这是一个原始函数,正如@AndreyChernyakhovskiy指出的那样?前者是否编译一次,然后放入库中?EDIT@Zeta刚刚用答案打败了我:)
writeCharBuffer h_@Handle__{..} !cbuf = do
-- much code omitted, like buffering
bbuf'' <- Buffered.flushWriteBuffer haDevice bbuf'
-- more code omitted, like buffering
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
instance BufferedIO FD where
-- some code omitted
flushWriteBuffer fd buf = writeBuf' fd buf
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)
foreign import capi unsafe "HsBase.h write"
c_write :: CInt -> Ptr Word8 -> CSize -> IO CSsize