Haskell中的IEEE浮点信令NaN(sNaN)

Ale*_*mov 8 floating-point haskell ieee-754

有没有办法在Haskell中定义信令NaN?我找到了两种处理NaN的方法:

1)使用0/0,产生相当的纳米

2)包Data.Number.Transfinite,它也没有信令NaN.

PS有没有办法在没有编写C库的情况下将Word64逐位放入Double中?

Ale*_*mov 2

我找到了一种非便携式方式:

{-# LANGUAGE ForeignFunctionInterface #-}
import Data.Word (Word64, Word32)
import Unsafe.Coerce
import Foreign
import Foreign.C.Types
foreign import ccall "fenv.h feenableexcept" -- GNU extension
    enableexcept :: CInt -> IO ()

class HasNAN a where
    signalingNaN :: a
    quietNaN :: a

instance HasNAN Double where
    signalingNaN = unsafeCoerce (0x7ff4000000000000::Word64)
    quietNaN = unsafeCoerce (0x7ff8000000000000::Word64)

instance HasNAN Float where
    signalingNaN = unsafeCoerce (0x7fa00000::Word32)
    quietNaN = unsafeCoerce (0x7fc00000::Word32)

main = do
    enableexcept 1 -- FE_INVALID in my system
    print $ show $ 1 + (quietNaN :: Float) -- works
    print $ show $ 1 + (signalingNaN :: Float) -- fails
Run Code Online (Sandbox Code Playgroud)

这完全失败了。事实证明,FPU 异常对于 Haskell 来说是一个坏主意。默认情况下它们被禁用是有充分理由的。如果您在 gdb 中调试 C/C++/其他内容,它们是可以的。我不想调试 Haskell 核心转储,因为它是非命令性的。启用FE_INVALID异常会导致 0/0 并添加到Data.Number.Transfinite和中的 NaN 中GHC.Real导致崩溃。但在enableexcept之前计算的0/0不会另外产生异常。

我将在我的任务中使用一些简单的错误检查。我sNaN只需要在一个地方。