簡體   English   中英

安全轉換為Word8

[英]Safe conversion to Word8

看一下以下片段:

Prelude> import Data.Word
Prelude> data Foo = Foo Word8 deriving Show
Prelude> Foo 4
Foo 4
Prelude> Foo 44
Foo 44
Prelude> Foo 444
Foo 188

我有點驚訝444被隱含地轉換為188,就像在不安全的C中一樣。它看起來很容易出錯。 在Haskell中安全處理此類轉換的慣用方法是什么?

UPDATE

看起來這只是文字的多態行為,現代編譯器對此提出警告。 最重要的是類型系統不允許這種隱式截斷。 Foo (444 :: Int)生成類型不匹配,因此如果僅在運行時知道值,則這是完全安全的。

最近向GHC發出警告,要求召集此類案件。 使用GHC 7.8.3,我看到:

Prelude Data.Word> Foo 444

<interactive>:7:5: Warning:
    Literal 444 is out of the Word8 range 0..255
Foo 188
Prelude Data.Word> 

編譯時:

$ ghc so.hs
[1 of 1] Compiling Main             ( so.hs, so.o )

so.hs:5:19: Warning: Literal 444 is out of the Word8 range 0..255

因此慣用的解決方案是使用最流行的編譯器的最新版本。

我不知道慣用語,但你遇到的問題基本上是文字在超出范圍時被截斷。 由於文字在Num上是多態的,而Integral需要Num ,因此你有這些函數

fromInteger :: Num a => Integer -> a
toInteger :: Integral a => a -> Integer

所以你總是可以在轉換之前將它們比作Integer

-- Don't export the constructor
data Foo = Foo Word8 deriving (Eq, Show)

foo :: Integral a => a -> Maybe Foo
foo x = if xI > mBW8I then Nothing else Just (Foo $ fromInteger xI)
    where
        xI = toInteger x
        mBW8 :: Word8
        mBW8 = maxBound
        mbW8I = toInteger mBW8

然后你可以使用foo作為智能構造函數:

> foo 4
Just (Foo 4)
> foo 44
Just (Foo 44)
> foo 444
Nothing

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM