{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TypeApplications #-}

-- |
-- 
-- Validation combinators that are backward compatible to v0.2 versions.
-- This module is re-exported in Data.TypedEncoding.
--
-- @since 0.3.0.0
module Data.TypedEncoding.Combinators.Validate where

import           Data.TypedEncoding.Combinators.Common
import           Data.TypedEncoding.Combinators.Unsafe
import           Data.TypedEncoding.Common.Types
import           Data.TypedEncoding.Common.Class.Validate
import           Data.TypedEncoding.Common.Class.Common (SymbolList)
import           Data.TypedEncoding.Common.Util.TypeLits (Append)
import           GHC.TypeLits
import           Data.Functor.Identity


-- * Validation

-- | Maybe signals annotation mismatch, effect @f@ is not evaluated unless there is match
checkWithValidations :: forall algs (nms :: [Symbol]) f c str . (
                    Monad f
                    , SymbolList nms
                    ) => Validations f nms algs c str -> UncheckedEnc c str -> Maybe (f (Enc nms c str))
checkWithValidations :: Validations f nms algs c str
-> UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
checkWithValidations Validations f nms algs c str
vers UncheckedEnc c str
x = 
      case UncheckedEnc c str -> Either String (UncheckedEnc c str)
forall (xs :: [Symbol]) c str.
SymbolList xs =>
UncheckedEnc c str -> Either String (UncheckedEnc c str)
verifyAnn @nms UncheckedEnc c str
x of
            Left String
err -> Maybe (f (Enc @[Symbol] nms c str))
forall a. Maybe a
Nothing -- asRecreateErr_ perr $ Left err
            Right (MkUncheckedEnc [String]
_ c
c str
str) -> f (Enc @[Symbol] nms c str) -> Maybe (f (Enc @[Symbol] nms c str))
forall a. a -> Maybe a
Just (f (Enc @[Symbol] nms c str)
 -> Maybe (f (Enc @[Symbol] nms c str)))
-> f (Enc @[Symbol] nms c str)
-> Maybe (f (Enc @[Symbol] nms c str))
forall a b. (a -> b) -> a -> b
$ Validations f nms algs c str
-> Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
forall (algs :: [Symbol]) (nms :: [Symbol]) (f :: * -> *) c str.
Monad f =>
Validations f nms algs c str
-> Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
recreateWithValidations Validations f nms algs c str
vers (Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str))
-> (str -> Enc @[Symbol] ('[] @Symbol) c str)
-> str
-> f (Enc @[Symbol] nms c str)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. c -> str -> Enc @[Symbol] ('[] @Symbol) c str
forall conf str.
conf -> str -> Enc @[Symbol] ('[] @Symbol) conf str
toEncoding c
c (str -> f (Enc @[Symbol] nms c str))
-> str -> f (Enc @[Symbol] nms c str)
forall a b. (a -> b) -> a -> b
$ str
str

check :: forall (nms :: [Symbol]) f c str . (
            Monad f
            ,  ValidateAll f nms nms c str
            , SymbolList nms
           ) => UncheckedEnc c str -> Maybe (f (Enc nms c str)) 
check :: UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
check = Validations f nms nms c str
-> UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
forall (algs :: [Symbol]) (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, SymbolList nms) =>
Validations f nms algs c str
-> UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
checkWithValidations @nms @nms @f Validations f nms nms c str
forall (f :: * -> *) (nms :: [Symbol]) (algs :: [Symbol]) conf str.
ValidateAll f nms algs conf str =>
Validations f nms algs conf str
validations 

check' :: forall algs (nms :: [Symbol]) f c str . (
            Monad f
            ,  ValidateAll f nms algs c str
            , SymbolList nms
           ) => UncheckedEnc c str -> Maybe (f (Enc nms c str)) 
check' :: UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
check' = Validations f nms algs c str
-> UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
forall (algs :: [Symbol]) (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, SymbolList nms) =>
Validations f nms algs c str
-> UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
checkWithValidations @algs @nms @f Validations f nms algs c str
forall (f :: * -> *) (nms :: [Symbol]) (algs :: [Symbol]) conf str.
ValidateAll f nms algs conf str =>
Validations f nms algs conf str
validations 


recreateWithValidations :: forall algs nms f c str . (Monad f) => Validations f nms algs c str -> Enc ('[]::[Symbol]) c str -> f (Enc nms c str)
recreateWithValidations :: Validations f nms algs c str
-> Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
recreateWithValidations Validations f nms algs c str
vers str :: Enc @[Symbol] ('[] @Symbol) c str
str@(UnsafeMkEnc Proxy @[Symbol] ('[] @Symbol)
_ c
_ str
pay) = 
        let Enc @[Symbol] nms c str
str0 :: Enc nms c str = (str -> str)
-> Enc @[Symbol] ('[] @Symbol) c str -> Enc @[Symbol] nms c str
forall k1 k2 s1 s2 (e1 :: k1) c (e2 :: k2).
(s1 -> s2) -> Enc @k1 e1 c s1 -> Enc @k2 e2 c s2
withUnsafeCoerce str -> str
forall a. a -> a
id Enc @[Symbol] ('[] @Symbol) c str
str
        in (str -> str)
-> Enc @[Symbol] ('[] @Symbol) c str -> Enc @[Symbol] nms c str
forall k1 k2 s1 s2 (e1 :: k1) c (e2 :: k2).
(s1 -> s2) -> Enc @k1 e1 c s1 -> Enc @k2 e2 c s2
withUnsafeCoerce (str -> str -> str
forall a b. a -> b -> a
const str
pay) (Enc @[Symbol] ('[] @Symbol) c str -> Enc @[Symbol] nms c str)
-> f (Enc @[Symbol] ('[] @Symbol) c str)
-> f (Enc @[Symbol] nms c str)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Validations f nms algs c str
-> Enc @[Symbol] nms c str -> f (Enc @[Symbol] ('[] @Symbol) c str)
forall (algs :: [Symbol]) (nms :: [Symbol]) (f :: * -> *) c str.
Monad f =>
Validations f nms algs c str
-> Enc @[Symbol] nms c str -> f (Enc @[Symbol] ('[] @Symbol) c str)
runValidationChecks' Validations f nms algs c str
vers Enc @[Symbol] nms c str
str0    

-- * v0.2 style recreate functions

recreateFAll :: forall nms f c str . (Monad f,  ValidateAll f nms nms c str) =>  
               Enc ('[]::[Symbol]) c str 
               -> f (Enc nms c str)  
recreateFAll :: Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
recreateFAll = forall (algs :: [Symbol]) (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms algs c str) =>
Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
forall (f :: * -> *) c str.
(Monad f, ValidateAll f nms nms c str) =>
Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
recreateFAll' @nms @nms 

recreateAll :: forall nms c str . (ValidateAll Identity nms nms c str) =>
               Enc ('[]::[Symbol]) c str 
               -> Enc nms c str 
recreateAll :: Enc @[Symbol] ('[] @Symbol) c str -> Enc @[Symbol] nms c str
recreateAll = forall (algs :: [Symbol]) (nms :: [Symbol]) c str.
ValidateAll Identity nms algs c str =>
Enc @[Symbol] ('[] @Symbol) c str -> Enc @[Symbol] nms c str
forall c str.
ValidateAll Identity nms nms c str =>
Enc @[Symbol] ('[] @Symbol) c str -> Enc @[Symbol] nms c str
recreateAll' @nms @nms  

recreateFPart :: forall xs xsf f c str . (Monad f, ValidateAll f xs xs c str) => Enc xsf c str -> f (Enc (Append xs xsf) c str)
recreateFPart :: Enc @[Symbol] xsf c str
-> f (Enc @[Symbol] (Append @Symbol xs xsf) c str)
recreateFPart = forall (algs :: [Symbol]) (xs :: [Symbol]) (xsf :: [Symbol])
       (f :: * -> *) c str.
(Monad f, ValidateAll f xs algs c str) =>
Enc @[Symbol] xsf c str
-> f (Enc @[Symbol] (Append @Symbol xs xsf) c str)
forall (xsf :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f xs xs c str) =>
Enc @[Symbol] xsf c str
-> f (Enc @[Symbol] (Append @Symbol xs xsf) c str)
recreateFPart' @xs @xs 

-- * Convenience combinators which mimic pre-v0.3 type signatures. These do not try to figure out @algs@ or assume much about them

recreateFAll' :: forall algs nms f c str . (Monad f,  ValidateAll f nms algs c str) =>  
               Enc ('[]::[Symbol]) c str 
               -> f (Enc nms c str)  
recreateFAll' :: Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
recreateFAll' = Validations f nms algs c str
-> Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
forall (algs :: [Symbol]) (nms :: [Symbol]) (f :: * -> *) c str.
Monad f =>
Validations f nms algs c str
-> Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
recreateWithValidations @algs @nms @f Validations f nms algs c str
forall (f :: * -> *) (nms :: [Symbol]) (algs :: [Symbol]) conf str.
ValidateAll f nms algs conf str =>
Validations f nms algs conf str
validations 

recreateAll' :: forall algs nms c str . (ValidateAll Identity nms algs c str) =>
               Enc ('[]::[Symbol]) c str 
               -> Enc nms c str 
recreateAll' :: Enc @[Symbol] ('[] @Symbol) c str -> Enc @[Symbol] nms c str
recreateAll' = Identity (Enc @[Symbol] nms c str) -> Enc @[Symbol] nms c str
forall a. Identity a -> a
runIdentity (Identity (Enc @[Symbol] nms c str) -> Enc @[Symbol] nms c str)
-> (Enc @[Symbol] ('[] @Symbol) c str
    -> Identity (Enc @[Symbol] nms c str))
-> Enc @[Symbol] ('[] @Symbol) c str
-> Enc @[Symbol] nms c str
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (algs :: [Symbol]) (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms algs c str) =>
Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
forall (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms algs c str) =>
Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
recreateFAll' @algs 

recreateFPart' :: forall algs xs xsf f c str . (Monad f, ValidateAll f xs algs c str) => Enc xsf c str -> f (Enc (Append xs xsf) c str)
recreateFPart' :: Enc @[Symbol] xsf c str
-> f (Enc @[Symbol] (Append @Symbol xs xsf) c str)
recreateFPart' = (Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] xs c str))
-> Enc @[Symbol] (Append @Symbol ('[] @Symbol) xsf) c str
-> f (Enc @[Symbol] (Append @Symbol xs xsf) c str)
forall (ts :: [Symbol]) (xs :: [Symbol]) (ys :: [Symbol])
       (f :: * -> *) c str.
Functor f =>
(Enc @[Symbol] xs c str -> f (Enc @[Symbol] ys c str))
-> Enc @[Symbol] (Append @Symbol xs ts) c str
-> f (Enc @[Symbol] (Append @Symbol ys ts) c str)
aboveF @xsf @'[] @xs (forall (algs :: [Symbol]) (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms algs c str) =>
Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
forall (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms algs c str) =>
Enc @[Symbol] ('[] @Symbol) c str -> f (Enc @[Symbol] nms c str)
recreateFAll' @algs) 

recreatePart' :: forall algs xs xsf c str . (ValidateAll Identity xs algs c str) => Enc xsf c str -> Enc (Append xs xsf) c str   
recreatePart' :: Enc @[Symbol] xsf c str
-> Enc @[Symbol] (Append @Symbol xs xsf) c str
recreatePart' = Identity (Enc @[Symbol] (Append @Symbol xs xsf) c str)
-> Enc @[Symbol] (Append @Symbol xs xsf) c str
forall a. Identity a -> a
runIdentity (Identity (Enc @[Symbol] (Append @Symbol xs xsf) c str)
 -> Enc @[Symbol] (Append @Symbol xs xsf) c str)
-> (Enc @[Symbol] xsf c str
    -> Identity (Enc @[Symbol] (Append @Symbol xs xsf) c str))
-> Enc @[Symbol] xsf c str
-> Enc @[Symbol] (Append @Symbol xs xsf) c str
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (algs :: [Symbol]) (xs :: [Symbol]) (xsf :: [Symbol])
       (f :: * -> *) c str.
(Monad f, ValidateAll f xs algs c str) =>
Enc @[Symbol] xsf c str
-> f (Enc @[Symbol] (Append @Symbol xs xsf) c str)
forall (xsf :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f xs algs c str) =>
Enc @[Symbol] xsf c str
-> f (Enc @[Symbol] (Append @Symbol xs xsf) c str)
recreateFPart' @algs @xs


--------------------------------------------