文字列が数値を表すか判定する
「数値を表す文字列」の解釈はいろいろありえます.
ここでは位取り記法についてのみ考え,
1. Text版としては,textパッケージに含まれる Data.Text.Read モジュールで提供されるリーダー関数で読み切れるテキスト
2. String版としては,baseパッケージに含まれる Numeric モジュールで提供されているリーダー関数で読み切れる文字列
がそれぞれ「数値を表す文字列」であると考えることにしましょう.
[*** Text版]
インポート
code: (haskell)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Read as T (decimal, hexadecimal, signed, double)
判別関数
code: (haskell)
-- | 整数10進表記か.
isDecimal :: Text -> Bool
isDecimal = either (const False) (T.null . snd) . T.signed T.decimal
-- | 整数16進表記か.
isHexadecimal :: Text -> Bool
isHexadecimal = either (const False) (T.null . snd) . T.signed T.hexadecimal
-- | 有理数位取り10進表記か.
isRational :: Text -> Bool
isRational = either (const False) (T.null . snd) . T.double
[*** String版]
インポート
code: (haskell)
import Data.Bool (bool)
import Numeric (readSigned, readDec, readHex, readFloat)
判別関数
code: (haskell)
-- | 整数10進表記か.
isDecimal' :: String -> Bool
isDecimal' s = bool (null $ snd $ head rs) False (null rs)
where
rs = readSinged readDec s
-- | 整数16進表記か.
isHexadecimal' :: String -> Bool
isHexadecimal' s = bool (null $ snd $ head rs) False (null rs)
where
rs = readSigned readHex s
-- | 有理数位取り10進表記か.
isRational' :: String -> Bool
isRational' s = bool (null $ snd $ head rs) False (null rs)
where
rs = readSigned readFloat s
使用(および仕様)上の注意
単純に実装した上述の判別関数はText版とString版とで以下の点で仕様に非互換なところがあります.
[** isDecimal(Text版)とisDecimal'(String版)]
isDecimalは+符号の前置しても結果は変りません.
isDecimal'は-符号と符号無し整数表記の間に白空白が複数挟まっても結果は変りません.
[** isHexadecimal(Text版)とisHexadecimal'(String版)]
isHexadecimalは+符号の前置しても結果は変りません.
isHexadecimalは0xを符号無し整数表記に前置しても結果は変りません.
isHexadecimal'は-符号と符号無し整数表記の間に白空白が複数挟まっても結果は変りません.
[** isRational(Text版)とisRational'(String版)]
isRationalは+符号の前置しても結果は変りません.
isRational'は0oあるいは0xをそれぞれ符号無し整数8進表記,符号無し整数16進表記に前置していればTrueになります.
isRational'は-符号と符号無し整数表記の間に白空白が複数挟まっても結果は変りません.
評価例
[** isDecimal]
code:_
>> :set -XOverloadedStrings
>> isDecimal "01234567890"
True
>> isDecimal "-01234567890"
True
>> isDecimal "- 01234567890"
False
>> isDecimal "1234.567890"
False
>> isDecimal "1,234,567,890"
False
>> isDecimal "0123456789abcdef"
False
>> isDecimal "123456789abcdefgh"
False
>> isDecimal "-0x123456789abcdef"
False
>> isDecimal "0x-123456789abcdef"
False
[** isHexadecimal]
code:_
>> :set -XOverloadedStrings
>> isHexadecimal "01234567890"
True
>> isHexadecimal "-01234567890"
True
>> isHexadecimal "- 01234567890"
False
>> isHexadecimal "1234.567890"
False
>> isHexadecimal "1,234,567,890"
False
>> isHexadecimal "0123456789abcdef"
True
>> isHexadecimal "123456789abcdefgh"
False
>> isHexadecimal "-0x123456789abcdef"
True
>> isHexadecimal "0x-123456789abcdef"
False
[** isRational]
code:_
>> :set -XOverloadedStrings
>> isRational "01234567890"
True
>> isRational "-01234567890"
True
>> isRational "- 01234567890"
False
>> isRational "1234.567890"
True
>> isRational "1,234,567,890"
False
>> isRational "0123456789abcdef"
False
>> isRational "123456789abcdefgh"
False
>> isRational "-0x123456789abcdef"
False
>> isRational "0x-123456789abcdef"
False
[** isDecimal']
code:_
>> isDecimal' "01234567890"
True
>> isDecimal' "-01234567890"
True
>> isDecimal' "- 01234567890"
True
>> isDecimal' "1234.567890"
False
>> isDecimal' "1,234,567,890"
False
>> isDecimal' "0123456789abcdef"
False
>> isDecimal' "123456789abcdefgh"
False
>> isDecimal' "-0x123456789abcdef"
False
>> isDecimal' "0x-123456789abcdef"
False
[** isHexadecimal']
code:_
>> isHexadecimal' "01234567890"
True
>> isHexadecimal' "-01234567890"
True
>> isHexadecimal' "- 01234567890"
True
>> isHexadecimal' "1234.567890"
False
>> isHexadecimal' "1,234,567,890"
False
>> isHexadecimal' "0123456789abcdef"
False
>> isHexadecimal' "123456789abcdefgh"
False
>> isHexadecimal' "-0x123456789abcdef"
False
>> isHexadecimal' "0x-123456789abcdef"
False
[** isRational']
code:_
>> isRational' "01234567890"
True
>> isRational' "-01234567890"
True
>> isRational' "- 01234567890"
True
>> isRational' "1234.567890"
True
>> isRational' "1,234,567,890"
False
>> isRational' "0123456789abcdef"
False
>> isRational' "123456789abcdefgh"
False
>> isRational' "-0o1234567"
True
>> isRational' "-0x123456789abcdef"
True
>> isRational' "-0o123.4567"
False
>> isRational' "-0x1234.56789abcdef"
False