{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} module Data.Foscam.File.DeviceId( DeviceId(..) , AsDeviceId(..) , deviceId , getDeviceIdCharacters ) where import Control.Applicative(Applicative((<*>)), (<$>)) import Control.Category(id, (.)) import Control.Lens(Optic', Choice, Fold, prism', (^?), ( # )) import Control.Monad(Monad) import Data.Char(Char) import Data.Eq(Eq) import Data.Foscam.File.DeviceIdCharacter import Data.Functor(fmap) 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 DeviceId = DeviceId DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter DeviceIdCharacter deriving (Eq, Ord, Show) class AsDeviceId p f s where _DeviceId :: Optic' p f s DeviceId instance AsDeviceId p f DeviceId where _DeviceId = id instance (p ~ (->), Applicative f) => AsDeviceIdCharacter p f DeviceId where _DeviceIdCharacter f (DeviceId d01 d02 d03 d04 d05 d06 d07 d08 d09 d10 d11 d12) = DeviceId <$> f d01 <*> f d02 <*> f d03 <*> f d04 <*> f d05 <*> f d06 <*> f d07 <*> f d08 <*> f d09 <*> f d10 <*> f d11 <*> f d12 instance (Choice p, Applicative f) => AsDeviceId p f String where _DeviceId = prism' (\(DeviceId d01 d02 d03 d04 d05 d06 d07 d08 d09 d10 d11 d12) -> fmap (_DeviceIdCharacter #) [d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11, d12]) (\s -> case s of [c01, c02, c03, c04, c05, c06, c07, c08, c09, c10, c11, c12] -> let f = (^? _DeviceIdCharacter) in DeviceId <$> f c01 <*> f c02 <*> f c03 <*> f c04 <*> f c05 <*> f c06 <*> f c07 <*> f c08 <*> f c09 <*> f c10 <*> f c11 <*> f c12 _ -> Nothing) getDeviceIdCharacters :: Fold DeviceId Char getDeviceIdCharacters = _DeviceIdCharacter . getDeviceIdCharacter -- | -- -- >>> parse deviceId "test" "AB0934233DEF" -- Right (DeviceId (DeviceIdCharacter 'A') (DeviceIdCharacter 'B') (DeviceIdCharacter '0') (DeviceIdCharacter '9') (DeviceIdCharacter '3') (DeviceIdCharacter '4') (DeviceIdCharacter '2') (DeviceIdCharacter '3') (DeviceIdCharacter '3') (DeviceIdCharacter 'D') (DeviceIdCharacter 'E') (DeviceIdCharacter 'F')) -- -- >>> parse deviceId "test" "AB0934233DEFabc" -- Right (DeviceId (DeviceIdCharacter 'A') (DeviceIdCharacter 'B') (DeviceIdCharacter '0') (DeviceIdCharacter '9') (DeviceIdCharacter '3') (DeviceIdCharacter '4') (DeviceIdCharacter '2') (DeviceIdCharacter '3') (DeviceIdCharacter '3') (DeviceIdCharacter 'D') (DeviceIdCharacter 'E') (DeviceIdCharacter 'F')) -- -- >>> parse deviceId "test" "AB0934233DX" -- Left "test" (line 1, column 12): -- not a device ID character: X -- -- >>> parse deviceId "test" "AB0934233DEf" -- Left "test" (line 1, column 13): -- not a device ID character: f -- -- >>> parse deviceId "test" "" -- Left "test" (line 1, column 1): -- unexpected end of input -- expecting device ID deviceId :: (Monad f, CharParsing f) => f DeviceId deviceId = DeviceId <$> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter <*> deviceIdCharacter "device ID"