{-# LANGUAGE PackageImports #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# language ConstraintKinds #-}
{-# language DataKinds #-}
{-# language FlexibleContexts #-}
{-# language FlexibleInstances #-}
{-# language FunctionalDependencies #-}
{-# language MultiParamTypeClasses #-}
{-# language ScopedTypeVariables #-}
{-# language TypeFamilies #-}
{-# language TypeOperators #-}
{-# language UndecidableInstances #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Generics.Wrapped
-- Copyright   :  (C) 2020 Csongor Kiss
-- License     :  BSD3
-- Maintainer  :  Csongor Kiss <kiss.csongor.kiss@gmail.com>
-- Stability   :  experimental
-- Portability :  non-portable
--
-- Derive an isomorphism between a newtype and its wrapped type.
--
-----------------------------------------------------------------------------

module Data.Generics.Wrapped
  ( Wrapped (..)
  , wrappedTo
  , wrappedFrom
  , _Unwrapped
  , _Wrapped
  )
where

import Optics.Core
import Optics.Internal.Optic

import "generic-lens-core" Data.Generics.Internal.Wrapped (Context, derived)


-- | @since 1.1.0.0
_Unwrapped :: Wrapped s t a b => Iso s t a b
_Unwrapped :: Iso s t a b
_Unwrapped = Iso s t a b
forall s t a b. Wrapped s t a b => Iso s t a b
wrappedIso
{-# inline _Unwrapped #-}

-- | @since 1.1.0.0
_Wrapped :: Wrapped s t a b => Iso b a t s
_Wrapped :: Iso b a t s
_Wrapped = Optic An_Iso NoIx s t a b
-> Optic (ReversedOptic An_Iso) NoIx b a t s
forall k (is :: IxList) s t a b.
(ReversibleOptic k, AcceptsEmptyIndices "re" is) =>
Optic k is s t a b -> Optic (ReversedOptic k) is b a t s
re Optic An_Iso NoIx s t a b
forall s t a b. Wrapped s t a b => Iso s t a b
wrappedIso
{-# inline _Wrapped #-}

-- | @since 1.1.0.0
class Wrapped s t a b | s -> a, t -> b where
  -- | @since 1.1.0.0
  wrappedIso :: Iso s t a b

-- | @since 1.1.0.0
wrappedTo :: forall s a. Wrapped s s a a => s -> a
wrappedTo :: s -> a
wrappedTo s
s = Optic' An_Iso NoIx s a -> s -> a
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view (Wrapped s s a a => Optic' An_Iso NoIx s a
forall s t a b. Wrapped s t a b => Iso s t a b
wrappedIso @s @s @a @a) s
s
{-# INLINE wrappedTo #-}

-- | @since 1.1.0.0
wrappedFrom :: forall s a. Wrapped s s a a => a -> s
wrappedFrom :: a -> s
wrappedFrom a
a = Optic' An_Iso NoIx a s -> a -> s
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view (Optic An_Iso NoIx s s a a
-> Optic (ReversedOptic An_Iso) NoIx a a s s
forall k (is :: IxList) s t a b.
(ReversibleOptic k, AcceptsEmptyIndices "re" is) =>
Optic k is s t a b -> Optic (ReversedOptic k) is b a t s
re Optic An_Iso NoIx s s a a
forall s t a b. Wrapped s t a b => Iso s t a b
wrappedIso) a
a
{-# INLINE wrappedFrom #-}

instance Context s t a b => Wrapped s t a b where
  wrappedIso :: Iso s t a b
wrappedIso = (forall (p :: * -> * -> * -> *) i.
 Profunctor p =>
 Optic_ An_Iso p i (Curry NoIx i) s t a b)
-> Iso s t a b
forall k (is :: IxList) s t a b.
(forall (p :: * -> * -> * -> *) i.
 Profunctor p =>
 Optic_ k p i (Curry is i) s t a b)
-> Optic k is s t a b
Optic forall s t a b. Context s t a b => Iso s t a b
forall (p :: * -> * -> * -> *) i.
Profunctor p =>
Optic_ An_Iso p i (Curry NoIx i) s t a b
derived
  {-# INLINE wrappedIso #-}