packages feed

barlow-lens-0.1.0.0: src/Data/Lens/Barlow/Construction.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

module Data.Lens.Barlow.Construction where

import Control.Lens (Optic, traversed, _Just, _Left, _Right)
import Control.Lens.Iso (Profunctor)
import Control.Lens.Prism (Choice)
import Data.Generics.Product.Fields (HasField (field))
import Data.Generics.Product.Positions (HasPosition (position))
import Data.Generics.Sum.Constructors (AsConstructor (_Ctor))
import Data.Generics.Wrapped (Wrapped (wrappedIso))
import Data.Lens.Barlow.Types (Tag (..))

-- Translated https://github.com/sigma-andex/purescript-barlow-lens/blob/main/src/Data/Lens/Barlow/Construction.purs

class ConstructBarlow (path :: [Tag]) p f s t a b | path s -> a, path t -> b where
  constructBarlow :: Optic p f s t a b

instance ConstructBarlow '[] p f s t s t where
  constructBarlow = id

instance (Choice p, ConstructBarlow path p f s t a b, Applicative f) => ConstructBarlow (Tag'RightArrow : path) p f (Either x s) (Either x t) a b where
  constructBarlow = _Right . constructBarlow @path

instance (Choice p, ConstructBarlow path p f s t a b, Applicative f) => ConstructBarlow (Tag'LeftArrow : path) p f (Either s x) (Either t x) a b where
  constructBarlow = _Left . constructBarlow @path

instance (Choice p, ConstructBarlow path p f q w a b, AsConstructor ctor s t q w, Applicative f) => ConstructBarlow (Tag'PercentageName ctor : path) p f s t a b where
  constructBarlow = _Ctor @ctor . constructBarlow @path

instance (p ~ (->), Applicative f, ConstructBarlow path p f s t a b, Traversable tr) => ConstructBarlow (Tag'Plus : path) p f (tr s) (tr t) a b where
  constructBarlow = traversed . constructBarlow @path

instance (Profunctor p, ConstructBarlow path p f q w a b, Functor f, Wrapped s t q w) => ConstructBarlow (Tag'ExclamationMark : path) p f s t a b where
  constructBarlow = wrappedIso . constructBarlow @path

instance (Choice p, ConstructBarlow path p f s t a b, Applicative f) => ConstructBarlow (Tag'QuestionMark : path) p f (Maybe s) (Maybe t) a b where
  constructBarlow = _Just . constructBarlow @path

instance (p ~ (->), Functor f, ConstructBarlow path p f q w a b, HasPosition pos s t q w) => ConstructBarlow (Tag'PercentageNumber pos : path) p f s t a b where
  constructBarlow = position @pos . constructBarlow @path

instance (p ~ (->), Functor f, ConstructBarlow path p f q w a b, HasField sym s t q w) => ConstructBarlow (Tag'Name sym : path) p f s t a b where
  constructBarlow = field @sym . constructBarlow @path