module Control.Isomorphism.Partial.Ext.Data (
succ, singleton,
readShow, negate, not, reverse,
digitInt, chrOrd, oct, hex,
signumAbs, digitsFloat, floatTripleDigits, floatTriple
) where
import Prelude hiding (id, succ, pred, negate, not, reverse, (.))
import qualified Prelude as P
import Control.Category ((.))
import Data.Maybe (listToMaybe)
import Data.Char (intToDigit, digitToInt, ord, chr)
import Data.List (foldl')
import Numeric (readOct, showOct, readHex, showHex, floatToDigits)
import Control.Isomorphism.Partial.Unsafe (Iso (Iso))
import Control.Isomorphism.Partial.Ext.Prim (iso)
succ :: Enum a => Iso a a
succ = Iso f g where
f = Just . P.succ
g n | fromEnum n <= 0 = Nothing
| otherwise = Just . P.pred $ n
singleton :: Iso a [a]
singleton = Iso f g where
f = Just . (:[])
g [x] = Just x
g _ = Nothing
readShow :: (Read a, Show a) => Iso String a
readShow = iso read show
negate :: Num a => Iso a a
negate = iso P.negate P.negate
not :: Iso Bool Bool
not = iso P.not P.not
reverse :: Iso [a] [a]
reverse = iso P.reverse P.reverse
digitInt :: Iso Char Int
digitInt = iso digitToInt intToDigit
chrOrd :: Iso Char Int
chrOrd = iso ord chr
oct :: (Integral a, Show a) => Iso String a
oct = Iso f g where
f = fmap fst . listToMaybe . readOct
g = Just . (`showOct` "")
hex :: (Integral a, Show a) => Iso String a
hex = Iso f g where
f = fmap fst . listToMaybe . readHex
g = Just . (`showHex` "")
signumAbs :: (Num a, Eq a) => Iso (a, a) a
signumAbs = iso f g where
f (x, y) = x * y
g 0 = (1, 0)
g v = (signum v, abs v)
digitsFloat :: RealFloat a => Iso ([Int], Int) a
digitsFloat = iso f g where
f (ds, e) | e' >= 0 = dv * 10 ^ e'
| otherwise = dv / 10 ^ ( e')
where dv = foldl' (\v d -> v * 10 + fromIntegral d) 0 ds
e' = e length ds
g = floatToDigits 10
floatTripleDigits :: Iso (String, (String, Int)) ([Int], Int)
floatTripleDigits = iso p q where
p (i, (f, e)) = (map digitToInt (i ++ f), length i + e)
q (ds, e) = ("", (map intToDigit ds, e))
floatTriple :: RealFloat a => Iso (String, (String, Int)) a
floatTriple = digitsFloat . floatTripleDigits