Int
时,我惊讶地发现没有错误被抛出:Prelude> read "123456789012345678901234567890" :: Int
-4362896299872285998
Text.Read
模块中的readMaybe
函数可以产生相同的结果。
有两个问题:
- 我应该调用哪个函数来执行安全转换?
- 地球上最类型安全的语言怎么会允许出现这样不安全的事情?
更新1:
这是我尝试编写一个检查边界的版本的read
函数:
{-# LANGUAGE ScopedTypeVariables #-}
parseIntegral :: forall a . (Integral a, Bounded a) => String -> Maybe a
parseIntegral s = integerToIntegral (read s :: Integer) where
integerToIntegral n | n < fromIntegral (minBound :: a) = Nothing
integerToIntegral n | n > fromIntegral (maxBound :: a) = Nothing
integerToIntegral n = Just $ fromInteger n
这是我能做到的最好吗?
Int
是一种模数算术类型,但通常人们选择它作为更高效的整数类型,或者因为它是列表函数使用的类型,而不是因为他们真正想要模数算术行为。 - Reid BartonInt
/Int16
的说法不正确 - 除非你已经知道你的String
在Int
的范围内,否则你必须通过lnteger
绕路 - 这里有一个例子read (show $ 2 * (fromIntegral (maxBound :: Int) :: Integer)) :: Int
这是一个 Int 溢出,但在流动-2
后在Int16
的范围内。 - epsilonhalbeInt
值,并在此过程中检查溢出。因此,您读取一个数字,将累加器乘以十,加上该数字,然后测试累加器是否在Int16
范围内。反复洗涤。这避免了读取Integer
值所涉及的所有分配(并且,糟糕的是,提醒我真的需要组合一个PR来实现Bertram Felgenhauer改进的“Integer”读取技术)。 - dfeuer