Haskell primPutChar definition

I am trying to understand how the basic functions of IO Haskell are defined, so I used this link and I got to putChar function definition:

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

Now, however, I cannot find more information about this primPutChar function anywhere. Maybe this could refer to a precompiled function available as a binary from a shared object? If so, is it possible to see its source code?

+6
source share
1 answer

What is prim*

Since you are asking this question in terms of the report, let's also answer this question in terms of the report:

Primitives that cannot be defined in Haskell, with names beginning with " prim ", are defined in a system-dependent manner in the PreludeBuiltin module and are not shown here.

By the way, in Haskell2010 everything is the same .

How it is implemented in the GHC

However, you can take a look at the base source to see how it is implemented in GHC:

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

From there you go deep into the rabbit hole. How can hPutChar print things? Well, that is not so. It only "buffers" and verifies that you can write:

 hPutChar :: Handle -> Char -> IO () hPutChar handle c = do c 'seq' return () wantWritableHandle "hPutChar" handle $ \ handle_ -> do hPutcBuffered handle_ c 

Writing is done in writeCharBuffer which fills the internal buffer until it is full (or a line is reached - it actually depends on the buffer mode):

 writeCharBuffer h_@Handle __{..} !cbuf = do -- much code omitted, like buffering bbuf'' <- Buffered.flushWriteBuffer haDevice bbuf' -- more code omitted, like buffering 

So where is flushWriteBuffer defined? This is 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 

And the file descriptor ( FD ) is an instance of BufferedIO :

 instance BufferedIO FD where -- some code omitted flushWriteBuffer fd buf = writeBuf' fd buf 

and writeBuf uses instance GHC.IO.Device.RawIO FD write , and that ultimately results in :

  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)

where we can see c_safe_write and c_write , which are usually bindings to C library functions:

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

So putChar uses write . At least in the implementation of the GHC. However, such an implementation is not required in the report, therefore another compiler / runtime is allowed to use other functions.

TL DR

The GHC implementation uses write with internal buffers to write things, including single characters.

+9
source

Source: https://habr.com/ru/post/1239345/


All Articles