{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE StarIsType #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Data.Managed.Encoding where

import Data.Kind (Type)

class Encoding a where
  type In a :: Type
  type Out a :: Type

class Encode t rep where
  encode :: t -> Out rep

class Decode t rep where
  decode :: In rep -> Maybe t

withEncoding ::
     forall e i o. (Encode o e, Decode i e)
  => (i -> o)
  -> In e
  -> Maybe (Out e)
withEncoding :: (i -> o) -> In e -> Maybe (Out e)
withEncoding i -> o
f In e
i = do
  i
decoded <- In e -> Maybe i
forall t rep. Decode t rep => In rep -> Maybe t
decode @i @e In e
i
  let applied :: o
applied = i -> o
f i
decoded
  Out e -> Maybe (Out e)
forall (m :: * -> *) a. Monad m => a -> m a
return (Out e -> Maybe (Out e)) -> Out e -> Maybe (Out e)
forall a b. (a -> b) -> a -> b
$ o -> Out e
forall t rep. Encode t rep => t -> Out rep
encode @o @e o
applied