content: {-# LANGUAGE CPP #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE UndecidableInstances #-}
  {-# LANGUAGE Trustworthy #-}
  
  {-# OPTIONS_GHC -fno-warn-orphans #-}
  
  #ifndef MIN_VERSION_base
  #define MIN_VERSION_base(x,y,z) 1
  #endif
  
  
  {- |
  Module      :  Lens.Micro.Platform
  Copyright   :  (C) 2013-2016 Edward Kmett, 2015-2016 Artyom Kazak, 2018 Monadfix
  License     :  BSD-style (see the file LICENSE)
  
  This module is an approximation for @<http://hackage.haskell.org/package/lens/docs/Control-Lens.html Control.Lens>@ from <http://hackage.haskell.org/package/lens lens>; by importing it you get all functions and instances from <http://hackage.haskell.org/package/microlens microlens>, <http://hackage.haskell.org/package/microlens-mtl microlens-mtl>, <http://hackage.haskell.org/package/microlens-ghc microlens-ghc>, as well as the following instances:
  
  * 'at' for 'HashMap'
  
  * 'each' and 'ix' for
  
      * 'HashMap'
      * 'Vector.Vector' and variants (unboxed vectors, etc)
      * strict 'T.Text' and lazy 'TL.Text'
  
  * '_head', '_tail', '_init', '_last' for
  
      * 'Vector.Vector' and variants
      * strict and lazy @Text@
  
  * 'strict' and 'lazy' for @Text@
  -}
  module Lens.Micro.Platform
  (
    module Lens.Micro,
    module Lens.Micro.GHC,
    module Lens.Micro.Mtl,
    module Lens.Micro.TH,
    packed, unpacked,
  )
  where
  
  
  import Lens.Micro.Internal
  import Lens.Micro
  import Lens.Micro.GHC
  import Lens.Micro.Mtl
  import Lens.Micro.TH
  import Lens.Micro.Platform.Internal
  
  import Data.Hashable
  import Data.Int
  import Data.Monoid
  import Data.Functor (($>))
  
  import Data.HashMap.Lazy as HashMap
  import Data.HashSet as HashSet
  import Data.Vector as Vector
  import Data.Vector.Primitive as Prim
  import Data.Vector.Storable as Storable
  import Data.Vector.Unboxed as Unboxed
  import Data.Vector.Generic as Generic
  
  import qualified Data.Text as T
  import qualified Data.Text.Lazy as TL
  
  #if !MIN_VERSION_base(4,8,0)
  import Control.Applicative
  #endif
  
  
  type instance Index   (HashMap k a) = k
  type instance IxValue (HashMap k a) = a
  type instance Index   (HashSet a) = a
  type instance IxValue (HashSet a) = ()
  type instance IxValue (HashMap k a) = a
  type instance Index   (Vector.Vector a) = Int
  type instance IxValue (Vector.Vector a) = a
  type instance Index   (Prim.Vector a) = Int
  type instance IxValue (Prim.Vector a) = a
  type instance Index   (Storable.Vector a) = Int
  type instance IxValue (Storable.Vector a) = a
  type instance Index   (Unboxed.Vector a) = Int
  type instance IxValue (Unboxed.Vector a) = a
  type instance Index   T.Text = Int
  type instance IxValue T.Text = Char
  type instance Index   TL.Text = Int64
  type instance IxValue TL.Text = Char
  
  instance (Eq k, Hashable k) => Ixed (HashMap k a) where
    ix k f m = case HashMap.lookup k m of
       Just v  -> f v <&> \v' -> HashMap.insert k v' m
       Nothing -> pure m
    {-# INLINE ix #-}
  
  instance (Eq k, Hashable k) => At (HashMap k a) where
    at k f m = f mv <&> \r -> case r of
      Nothing -> maybe m (const (HashMap.delete k m)) mv
      Just v' -> HashMap.insert k v' m
      where mv = HashMap.lookup k m
    {-# INLINE at #-}
  
  instance (Eq k, Hashable k) => Ixed (HashSet k) where
    ix k f m = if HashSet.member k m
       then f () $> m
       else pure m
    {-# INLINE ix #-}
  
  instance (Eq k, Hashable k) => At (HashSet k) where
    at k f s = HashSet.fromMap <$> HashMap.alterF f k (HashSet.toMap s)
    {-# INLINE at #-}
  
  instance Ixed (Vector.Vector a) where
    ix i f v
      | 0 <= i && i < Vector.length v = f (v Vector.! i) <&> \a -> v Vector.// [(i, a)]
      | otherwise                     = pure v
    {-# INLINE ix #-}
  
  instance Prim a => Ixed (Prim.Vector a) where
    ix i f v
      | 0 <= i && i < Prim.length v = f (v Prim.! i) <&> \a -> v Prim.// [(i, a)]
      | otherwise                   = pure v
    {-# INLINE ix #-}
  
  instance Storable a => Ixed (Storable.Vector a) where
    ix i f v
      | 0 <= i && i < Storable.length v = f (v Storable.! i) <&> \a -> v Storable.// [(i, a)]
      | otherwise                       = pure v
    {-# INLINE ix #-}
  
  instance Unbox a => Ixed (Unboxed.Vector a) where
    ix i f v
      | 0 <= i && i < Unboxed.length v = f (v Unboxed.! i) <&> \a -> v Unboxed.// [(i, a)]
      | otherwise                      = pure v
    {-# INLINE ix #-}
  
  instance Ixed T.Text where
    ix e f s = case T.splitAt e s of
       (l, mr) -> case T.uncons mr of
         Nothing      -> pure s
         Just (c, xs) -> f c <&> \d -> T.concat [l, T.singleton d, xs]
    {-# INLINE ix #-}
  
  instance Ixed TL.Text where
    ix e f s = case TL.splitAt e s of
       (l, mr) -> case TL.uncons mr of
         Nothing      -> pure s
         Just (c, xs) -> f c <&> \d -> TL.append l (TL.cons d xs)
    {-# INLINE ix #-}
  
  instance Cons T.Text T.Text Char Char where
    _Cons f s = case T.uncons s of
      Just x  -> uncurry T.cons <$> f x
      Nothing -> pure T.empty
    {-# INLINE _Cons #-}
  
  instance Cons TL.Text TL.Text Char Char where
    _Cons f s = case TL.uncons s of
      Just x  -> uncurry TL.cons <$> f x
      Nothing -> pure TL.empty
    {-# INLINE _Cons #-}
  
  instance Snoc T.Text T.Text Char Char where
    _Snoc f s = if T.null s
      then pure T.empty
      else uncurry T.snoc <$> f (T.init s, T.last s)
    {-# INLINE _Snoc #-}
  
  instance Snoc TL.Text TL.Text Char Char where
    _Snoc f s = if TL.null s
      then pure TL.empty
      else uncurry TL.snoc <$> f (TL.init s, TL.last s)
    {-# INLINE _Snoc #-}
  
  instance Cons (Vector.Vector a) (Vector.Vector b) a b where
    _Cons f s = if Vector.null s
      then pure Vector.empty
      else uncurry Vector.cons <$> f (Vector.unsafeHead s, Vector.unsafeTail s)
    {-# INLINE _Cons #-}
  
  instance (Prim a, Prim b) => Cons (Prim.Vector a) (Prim.Vector b) a b where
    _Cons f s = if Prim.null s
      then pure Prim.empty
      else uncurry Prim.cons <$> f (Prim.unsafeHead s, Prim.unsafeTail s)
    {-# INLINE _Cons #-}
  
  instance (Storable a, Storable b) => Cons (Storable.Vector a) (Storable.Vector b) a b where
    _Cons f s = if Storable.null s
      then pure Storable.empty
      else uncurry Storable.cons <$> f (Storable.unsafeHead s, Storable.unsafeTail s)
    {-# INLINE _Cons #-}
  
  instance (Unbox a, Unbox b) => Cons (Unboxed.Vector a) (Unboxed.Vector b) a b where
    _Cons f s = if Unboxed.null s
      then pure Unboxed.empty
      else uncurry Unboxed.cons <$> f (Unboxed.unsafeHead s, Unboxed.unsafeTail s)
    {-# INLINE _Cons #-}
  
  instance Snoc (Vector.Vector a) (Vector.Vector b) a b where
    _Snoc f s = if Vector.null s
      then pure Vector.empty
      else uncurry Vector.snoc <$> f (Vector.unsafeInit s, Vector.unsafeLast s)
    {-# INLINE _Snoc #-}
  
  instance (Prim a, Prim b) => Snoc (Prim.Vector a) (Prim.Vector b) a b where
    _Snoc f s = if Prim.null s
      then pure Prim.empty
      else uncurry Prim.snoc <$> f (Prim.unsafeInit s, Prim.unsafeLast s)
    {-# INLINE _Snoc #-}
  
  instance (Storable a, Storable b) => Snoc (Storable.Vector a) (Storable.Vector b) a b where
    _Snoc f s = if Storable.null s
      then pure Storable.empty
      else uncurry Storable.snoc <$> f (Storable.unsafeInit s, Storable.unsafeLast s)
    {-# INLINE _Snoc #-}
  
  instance (Unbox a, Unbox b) => Snoc (Unboxed.Vector a) (Unboxed.Vector b) a b where
    _Snoc f s = if Unboxed.null s
      then pure Unboxed.empty
      else uncurry Unboxed.snoc <$> f (Unboxed.unsafeInit s, Unboxed.unsafeLast s)
    {-# INLINE _Snoc #-}
  
  instance Each (Vector.Vector a) (Vector.Vector b) a b where
    each = vectorTraverse
    {-# INLINE each #-}
  
  instance (Prim a, Prim b) => Each (Prim.Vector a) (Prim.Vector b) a b where
    each = vectorTraverse
    {-# INLINE each #-}
  
  instance (Storable a, Storable b) => Each (Storable.Vector a) (Storable.Vector b) a b where
    each = vectorTraverse
    {-# INLINE each #-}
  
  instance (Unbox a, Unbox b) => Each (Unboxed.Vector a) (Unboxed.Vector b) a b where
    each = vectorTraverse
    {-# INLINE each #-}
  
  instance (c ~ d) => Each (HashMap c a) (HashMap d b) a b where
    each = traversed
    {-# INLINE each #-}
  
  instance (a ~ Char, b ~ Char) => Each T.Text T.Text a b where
    each = strictText
    {-# INLINE each #-}
  
  instance (a ~ Char, b ~ Char) => Each TL.Text TL.Text a b where
    each = lazyText
    {-# INLINE each #-}
  
  strictUnpacked :: Lens' T.Text String
  strictUnpacked f t = T.pack <$> f (T.unpack t)
  {-# INLINE strictUnpacked #-}
  
  strictText :: Traversal' T.Text Char
  strictText = strictUnpacked . traversed
  {-# INLINE [0] strictText #-}
  
  {-# RULES
  "strict text -> map"    strictText = sets T.map        :: ASetter' T.Text Char;
  "strict text -> foldr"  strictText = foldring T.foldr  :: Getting (Endo r) T.Text Char;
   #-}
  
  lazyUnpacked :: Lens' TL.Text String
  lazyUnpacked f t = TL.pack <$> f (TL.unpack t)
  {-# INLINE lazyUnpacked #-}
  
  lazyText :: Traversal' TL.Text Char
  lazyText = lazyUnpacked . traversed
  {-# INLINE [0] lazyText #-}
  
  {-# RULES
  "lazy text -> map"    lazyText = sets TL.map        :: ASetter' TL.Text Char;
  "lazy text -> foldr"  lazyText = foldring TL.foldr  :: Getting (Endo r) TL.Text Char;
   #-}
  
  vectorTraverse :: (Generic.Vector v a, Generic.Vector w b) => Traversal (v a) (w b) a b
  vectorTraverse f v = Generic.fromListN (Generic.length v) <$> traversed f (Generic.toList v)
  {-# INLINE [0] vectorTraverse #-}
  
  {-# RULES
  "vectorTraverse -> mapped" vectorTraverse  = sets Generic.map         :: (Generic.Vector v a, Generic.Vector v b) => ASetter (v a) (v b) a b;
  "vectorTraverse -> foldr"  vectorTraverse  = foldring Generic.foldr   :: Generic.Vector v a => Getting (Endo r) (v a) a;
   #-}
  
  instance Strict TL.Text T.Text where
    strict f s = TL.fromStrict <$> f (TL.toStrict s)
    {-# INLINE strict #-}
    lazy f s = TL.toStrict <$> f (TL.fromStrict s)
    {-# INLINE lazy #-}
  