{-# LANGUAGE MultiParamTypeClasses , TypeSynonymInstances , FlexibleInstances #-} module Data.ByteString.Nums.Careless.Float where import Prelude hiding (break, length, null, drop, tail, head) import Data.ByteString hiding (head, break, pack) import Data.ByteString.Char8 hiding (inits, elem, last, foldl') import qualified Data.ByteString.Lazy.Internal as Lazy import qualified Data.ByteString.Lazy.Char8 as Lazy import Data.ByteString.Nums.Careless.Int {-| Types that can be read from floating point strings. A floating point string is taken to be a string of digits with up to one comma or period mixed in with the digits. -} class (Intable b f, Fractional f) => Floatable b f where float :: b -> f instance Floatable ByteString Float where float = strict_float instance Floatable ByteString Double where float = strict_float instance Floatable ByteString Rational where float = strict_float instance Floatable Lazy.ByteString Float where float = lazy_float instance Floatable Lazy.ByteString Double where float = lazy_float instance Floatable Lazy.ByteString Rational where float = lazy_float strict_float :: (Fractional f) => ByteString -> f strict_float bytes | null bytes = 0 | head bytes == '-' = foldn 0 (tail integer) + nfrac | head bytes == '+' = foldp 0 (tail integer) + pfrac | otherwise = foldp 0 integer + pfrac where foldn = foldl' negative foldp = foldl' positive (integer, fractional) = break point bytes fractional' = tail fractional p = 0.1 ^ length fractional' nfrac | null fractional = 0 | otherwise = foldn 0 fractional' * p pfrac | null fractional = 0 | otherwise = foldp 0 fractional' * p lazy_float :: (Fractional f) => Lazy.ByteString -> f lazy_float bytes | Lazy.null bytes = 0 | Lazy.head bytes == '-' = foldn 0 (Lazy.tail integer) + nfrac | Lazy.head bytes == '+' = foldp 0 (Lazy.tail integer) + pfrac | otherwise = foldp 0 integer + pfrac where foldn = Lazy.foldlChunks (foldl' negative) foldp = Lazy.foldlChunks (foldl' positive) (integer, fractional) = Lazy.break point bytes fractional' = Lazy.tail fractional p = 0.1 ^ Lazy.length fractional' nfrac | Lazy.null fractional = 0 | otherwise = foldn 0 fractional' * p pfrac | Lazy.null fractional = 0 | otherwise = foldp 0 fractional' * p point :: Char -> Bool point c = c == '.' || c == ','