{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveFunctor, UndecidableInstances, StandaloneDeriving #-}
-- reference https://www.youtube.com/watch?v=BHjIl81HgfE
data MyType lst c = MyType {
        myList :: lst Int
    ,   myContent :: c
    } deriving (Functor)
    
instance (Show (lst Int), Show c) => Show (MyType lst c) where
    show (MyType l c) = "MyType " ++ show l ++ " " ++ show c
    
newtype Parsed a = Parsed a 
deriving instance Show a => Show (Parsed a)
type DefaultMyType = MyType [] ()
type HalfBakedMyType c = MyType [] c
type FullyBackedMyType c = MyType [] (Parsed c)
defaultMyType :: DefaultMyType
defaultMyType = MyType [] ()
halfBake :: c -> DefaultMyType -> HalfBakedMyType c
halfBake s = fmap (const s)
fullyBake :: Foldable t => MyType lst (t a) -> MyType [] (Parsed (t a))
fullyBake t = t { myContent = Parsed (myContent t), myList = [1 .. length (myContent t)] }
main = do
    print defaultMyType
    let stepOne = halfBake "some content" defaultMyType
    print stepOne
    let stepTwo = fullyBake stepOne
    print stepTwo