deka-0.2.0.0: lib/Data/Deka/Internal.hs
-- | Internal types - for Deka use only
--
-- This module is not listed for export in the cabal file. It
-- contains types that library users have no access to, but which
-- are needed by multiple Deka modules or that the test suite needs
-- access to.
module Data.Deka.Internal where
import Foreign.Safe
import Foreign.C
import qualified Data.ByteString.Char8 as BS8
import Data.Deka.Decnumber
import Control.Applicative
import Control.Monad
import System.IO.Unsafe (unsafePerformIO)
-- | The Ctx monad
--
-- The General Decimal Arithmetic specification states that most
-- computations occur within a @context@, which affects the manner
-- in which computations are done (for instance, the context
-- determines the rounding algorithm). The context also carries
-- the flags that computations can set (for instance, a computation might
-- set a flag to indicate that the result is rounded or inexact or
-- was a division by zero.) The Ctx monad carries this context.
newtype Ctx a = Ctx { unCtx :: Ptr C'decContext -> IO a }
instance Functor Ctx where
fmap = liftM
instance Applicative Ctx where
pure = return
(<*>) = ap
instance Monad Ctx where
return a = Ctx $ \_ -> return a
Ctx a >>= f = Ctx $ \p -> do
r1 <- a p
let b = unCtx $ f r1
b p
fail s = Ctx $ \_ -> fail s
-- | Decimal number. As indicated in the General Decimal
-- Arithmetic specification, a 'Quad' might be a finite number
-- (perhaps the most common type) or it might be infinite or a
-- not-a-number. 'decClass' will tell you a little more about a
-- particular 'Quad'.
newtype Quad = Quad { unQuad :: ForeignPtr C'decQuad }
-- | The Show instance uses 'toByteString'.
instance Show Quad where
show = BS8.unpack . toByteString
-- | Converts a 'Quad' to a string. May use non-scientific
-- notation, but only if that's unambiguous; otherwise, uses
-- scientific notation.
--
-- In the decNumber C library, this is called @toString@; the name
-- was changed here because this function doesn't return a Haskell
-- 'String'.
toByteString :: Quad -> BS8.ByteString
toByteString = mkString unsafe'c'decQuadToString
type MkString
= Ptr C'decQuad
-> CString
-> IO CString
mkString
:: MkString
-> Quad
-> BS8.ByteString
mkString f d = unsafePerformIO $
withForeignPtr (unQuad d) $ \pD ->
allocaBytes c'DECQUAD_String $ \pS ->
f pD pS
>> BS8.packCString pS