module Math.Checksum.EAN (checksum, valid) where
import qualified Math.Checksum.Utility as Util
import Control.Monad.Exception.Synchronous (Exceptional)
import qualified Data.List as List
checksum :: String -> Exceptional String Int
checksum xs = do
ws <- mapM Util.intFromDigit xs
return $ 9 - remainder (ws++[9])
valid :: String -> Maybe String
valid xs = Util.processValid $ do
ws <- mapM Util.intFromDigit xs
return (0 == remainder ws)
_remainder :: [Int] -> Int
_remainder ws = mod (sum $ zipWith (*) (cycle [1,3]) (reverse ws)) 10
remainder :: [Int] -> Int
remainder ws =
let (x,y) = sum2 ws
in mod (3*x+y) 10
sum2 :: (Num a) => [a] -> (a,a)
sum2 = List.foldl' (\(a,b) x -> strictPair b (a+x)) (0,0)
strictPair :: a -> b -> (a,b)
strictPair a b = ((,) $! a) $! b