{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} module Data.Foscam.File.Date( Date(..) , AsDate(..) , date ) where import Control.Applicative(Applicative((<*>)), (<$>)) import Control.Category(Category(id)) import Control.Lens(Optic', Choice, prism', (^?), (#)) import Control.Monad(Monad) import Data.Digit(Digit, digitC) import Data.Eq(Eq) import Data.Foscam.File.Internal(digitCharacter) import Data.Maybe(Maybe(Nothing)) import Data.Ord(Ord) import Data.String(String) import Text.Parser.Char(CharParsing) import Text.Parser.Combinators(()) import Prelude(Show) -- $setup -- >>> import Text.Parsec data Date = Date Digit Digit Digit Digit Digit Digit Digit Digit deriving (Eq, Ord, Show) class AsDate p f s where _Date :: Optic' p f s Date instance AsDate p f Date where _Date = id instance (Choice p, Applicative f) => AsDate p f String where _Date = prism' (\(Date d01 d02 d03 d04 d05 d06 d07 d08) -> (digitC #) <$> [d01, d02, d03, d04, d05, d06, d07, d08]) (\s -> case s of [c01, c02, c03, c04, c05, c06, c07, c08] -> let f = (^? digitC) in Date <$> f c01 <*> f c02 <*> f c03 <*> f c04 <*> f c05 <*> f c06 <*> f c07 <*> f c08 _ -> Nothing) -- | -- -- >>> parse date "test" "20140508" -- Right (Date 2 0 1 4 0 5 0 8) -- -- >>> parse date "test" "20140508abc" -- Right (Date 2 0 1 4 0 5 0 8) -- -- >>> parse date "test" "201405" -- Left "test" (line 1, column 7): -- unexpected end of input -- expecting digit -- -- >>> parse date "test" "201405a9" -- Left "test" (line 1, column 8): -- not a digit: a -- -- >>> parse date "test" "" -- Left "test" (line 1, column 1): -- unexpected end of input -- expecting date date :: (Monad f, CharParsing f) => f Date date = Date <$> digitCharacter <*> digitCharacter <*> digitCharacter <*> digitCharacter <*> digitCharacter <*> digitCharacter <*> digitCharacter <*> digitCharacter "date"