import Data.List (span)




data Nest a = Nest (Maybe a) [Nest a]
  deriving Eq

instance Show a => Show (Nest a) where
  show (Nest (Just a) []) = show a
  show (Nest (Just a) s) = show a ++ show s
  show (Nest Nothing []) = "\"\""
  show (Nest Nothing s) = "\"\"" ++ show s


type Indent a = [(Int, a)]


class Iso b a => Iso a b where
  from :: a -> b


instance Iso (Nest a) (Indent a) where
  from = go (-1)
    where
      go n (Nest a t) =
        case a of
          Just a -> (n, a): foldMap (go (n + 1)) t 
          Nothing -> foldMap (go (n + 1)) t


instance Iso (Indent a) (Nest a) where
  from = revNest . foldl add (Nest Nothing [])
    where
      add t (d,x) = go 0 t
        where
          go n (Nest a s) =
            case compare n d of
              EQ -> Nest a $ Nest (Just x) []: s
              LT -> case s of
                      h:t -> Nest a $ go (n+1) h: t
                      [] -> go n $ Nest a [Nest Nothing []]
              GT -> go (n-1) $ Nest Nothing [Nest a s]

      revNest (Nest a s) = Nest a (reverse $ revNest <$> s)  


instance Iso (Indent String) String where
  from = unlines . map process
    where
      process (d, s) = replicate (4*d) ' ' ++ s


instance Iso String (Indent String) where
  from = map process . lines
    where
      process s = let (i, a) = span (== ' ') s
                  in (length i `div` 4, a)


instance Iso (Nest String) String where
  from = from @(Indent String) . from


instance Iso String (Nest String) where
  from = from @(Indent String) . from