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

-- | Type classes accompanying decoding types defined in "Data.TypedEncoding.Common.Types.Enc"
--
-- "Examples.TypedEncoding.Instances.DiySignEncoding" contains an implementation example.
--
-- "Examples.TypedEncoding.Overview" shows decoding usage examples.
-- 
-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly.

module Data.TypedEncoding.Common.Class.Encode where

import           Data.TypedEncoding.Common.Types.Enc


-- | 
-- Using 2 Symbol type variables (@nm@ and @alg@) creates what seems like redundant typing
-- in statically defined instances such as @"r-ASCII"@, however it 
-- provides future flexibility to 
-- constrain @nm@ in some interesting way, different than @AlgNm nm ~ alg@. 
--
-- It also seems to be easier to understand as type variables used in the definition of 'Encoding'
-- match with what is on the typeclass.
--
-- @alg@ is expected to be very statically defined and is needed to support more open instances such as @"r-ban"@.
--
-- @since 0.3.0.0
class Encode f nm alg conf str where
    encoding :: Encoding f nm alg conf str

-- |
-- @since 0.3.0.0
class EncodeAll f nms algs conf str where
    encodings :: Encodings f nms algs conf str

instance EncodeAll f '[] '[] conf str where
    encodings = ZeroE

instance (EncodeAll f nms algs conf str, Encode f nm alg conf str) => EncodeAll f (nm ': nms) (alg ': algs) conf str where
    encodings = ConsE encoding encodings