matrix-as-xyz-0.1.1.0: src/Data/Ratio/Slash.hs
{- |
Module : Data.Ratio.Slash
Copyright : (c) Jun Narumi 2018
License : BSD3
Maintainer : narumij@gmail.com
Stability : experimental
Portability : ?
Handle fractions described in /, not%
-}
module Data.Ratio.Slash (
Slash(..),
) where
import Control.Monad (guard)
import Control.Applicative ((<|>))
import Data.Ratio
import Numeric
-- | Type of read and show slash form rational
--
-- >>> getRatio . read $ "1/2"
-- 1 % 2
--
-- >>> map getRatio . read $ "[1/2,3/4,5/6]"
-- [1 % 2,3 % 4,5 % 6]
--
-- >>> Slash (1 % 2)
-- 1/2
--
-- >>> map Slash [1%2,3%4,5%6]
-- [1/2,3/4,5/6]
--
newtype Slash a
= Slash {
getRatio :: Ratio a
} deriving (Eq,Ord)
instance (Integral a) => Show (Slash a) where
showsPrec _ (Slash n)
| denominator n == 1
= showSigned showInt 0 (numerator n)
| otherwise
= showSigned showInt 0 (numerator n) . showString "/" . showInt (denominator n)
instance (Integral a) => Read (Slash a) where
readsPrec _ n = do
( ( n, d ), st ) <- slashOrInteger n
guard $ d /= 0
return ( Slash $ n % d , st )
integer :: (Integral a) => ReadS (a,a)
integer n = do
( n, st ) <- readSigned readDec n
return ( ( n, 1 ), st )
slash :: (Integral a) => ReadS (a,a)
slash n = do
( numer, st ) <- readSigned readDec n
( "/" , st1 ) <- lex st
( denom, st2 ) <- readDec st1
return ( ( numer, denom ), st2)
slashOrInteger :: (Integral a) => ReadS (a,a)
slashOrInteger n = take 1 $ slash n <|> integer n