maint(live): remove unused `Control.Monad.Classes`
[haskell/literate-web.git] / src / Literate / Web / Semantics / Compiler.hs
index ec485c963a43142f7ebb872ce9d3fb42c1d6d94a..d62b9ba500e129cc9be047bb8f4c55e9576744c6 100644 (file)
@@ -1,45 +1,34 @@
--- For CompilerToF
-{-# LANGUAGE ConstraintKinds #-}
--- For Output
-{-# LANGUAGE DeriveFunctor #-}
--- For CompilerToF
-{-# LANGUAGE UndecidableInstances #-}
--- For CompilerToF
-{-# LANGUAGE AllowAmbiguousTypes #-}
+-- For Dataable instances
+{-# LANGUAGE InstanceSigs #-}
 -- For Output
 {-# LANGUAGE RankNTypes #-}
--- For Dataable__
-{-# LANGUAGE InstanceSigs #-}
+-- For Dataable instances
+{-# LANGUAGE UndecidableInstances #-}
 
 module Literate.Web.Semantics.Compiler where
 
 import Control.Applicative (Applicative (..))
-import Control.Monad (Monad (..), forM, forM_, join, sequence, (>=>))
+import Control.Monad (Monad (..), forM_)
 import Control.Monad.Classes qualified as MC
-import Control.Monad.Trans.Class qualified as MT
-import Control.Monad.Trans.Reader qualified as MT
 import Data.Bool
-import Data.ByteString.Lazy qualified as BSL
+import Data.ByteString.Builder qualified as BSB
 import Data.Either (Either (..))
-import Data.Eq (Eq (..))
+import Data.Eq (Eq)
 import Data.Foldable (toList)
-import Data.Function (const, id, ($), (.))
+import Data.Function (id, ($), (.))
 import Data.Functor (Functor (..), (<$>))
-import Data.Kind (Constraint, Type)
 import Data.List qualified as List
+import Data.Map.Strict qualified as Map
 import Data.Maybe (Maybe (..))
-import Data.Ord (Ord (..))
+import Data.Monoid (Monoid (..))
+import Data.Ord (Ord)
 import Data.Proxy (Proxy (..))
 import Data.Semigroup (Semigroup (..))
-import Data.String (fromString)
 import Data.Text (Text)
 import Data.Text qualified as Text
-import Data.Tuple (curry, fst, snd)
+import Data.Tuple (fst, snd)
 import GHC.Generics (Generic)
 import GHC.Stack (HasCallStack)
-import Literate.Web.Syntaxes
-import Literate.Web.Types.MIME
-import Literate.Web.Types.URL
 import Symantic qualified as Sym
 import System.Directory qualified as Sys
 import System.FilePath qualified as Sys
@@ -47,87 +36,76 @@ import System.FilePattern.Directory qualified as Sys
 import System.IO qualified as Sys
 import Text.Show (Show (..))
 import Type.Reflection ((:~:) (..))
-import Prelude (undefined)
+
+import Literate.Web.Syntaxes
+import Literate.Web.Types.MIME
+import Literate.Web.Types.URL
 
 -- * Type 'Compiler'
-newtype Compiler m a = Compiler {unCompiler :: {-FIXME: is m required?-}m [Output a]}
-  -- deriving (Functor)
+
+-- | Interpreter building a static Web site.
+--
+-- Embed a 'Monad' @m@ to give access to a model if need be.
+newtype Compiler m a = Compiler {unCompiler :: m [Output a]}
+
+data CompilerEndpoint m a next = CompilerEndpoint
+  { compilerEndpointProof :: next :~: m BSB.Builder
+  , compilerEndpointData :: a
+  }
+type instance Sym.ToFEndpoint (Compiler m) a next = CompilerEndpoint m a next
+
+compilerEndpoint :: a -> CompilerEndpoint m a (m BSB.Builder)
+compilerEndpoint = CompilerEndpoint Refl
+
+compiler :: Compiler m (m BSB.Builder) -> Compiler m (m BSB.Builder)
+compiler = id
 
 compile ::
   MC.MonadExec Sys.IO m =>
   CompilerEnv ->
   Compiler m a ->
-  CompilerToF a (m BSL.ByteString) ->
+  (a --> m BSB.Builder) ->
   m ()
 compile CompilerEnv{..} router content = do
   outputs <- unCompiler router
   MC.exec @Sys.IO $ Sys.removePathForcibly compilerEnvDest
-  forM_ outputs $ \Output{..} -> do
-    let destPath =
-          ( List.intercalate "." $
-              encodePath outputPath :
-              ( if List.null outputExts
-                  then ["txt"]
-                  else Text.unpack . encodePathSegment <$> outputExts
-              )
-          )
-    -- hPutStrLn stderr $ "mkdir: " <> show (Sys.takeDirectory destPath)
+  forM_ outputs $ \out -> do
+    let outFullPath = outputPathFile (outputPathRelative out)
+    -- MC.exec $ Sys.hPutStrLn Sys.stderr $ "mkdir: " <> show (Sys.takeDirectory outFullPath)
     MC.exec @Sys.IO $
       Sys.createDirectoryIfMissing True $
-        compilerEnvDest Sys.</> Sys.takeDirectory destPath
-    -- hPutStrLn stderr $ "write: " <> show destPath
-    bsl <- outputData content
-    MC.exec @Sys.IO $
-      BSL.writeFile (compilerEnvDest Sys.</> destPath) $
-        bsl
-
-
-compi :: Compiler m (m BSL.ByteString) -> Compiler m (m BSL.ByteString)
-compi = id
+        compilerEnvDest Sys.</> Sys.takeDirectory outFullPath
+    -- MC.exec $ Sys.hPutStrLn Sys.stderr $ "write: " <> show outFullPath
+    bsb <- outputData out content
+    MC.exec @Sys.IO do
+      Sys.withBinaryFile (compilerEnvDest Sys.</> outFullPath) Sys.WriteMode $ \h -> do
+        BSB.hPutBuilder h bsb
 
--- compile2 ::
---   MC.MonadExec Sys.IO m =>
---   CompilerEnv ->
---   Compiler m (m BSL.ByteString) ->
---   m ()
--- compile2 CompilerEnv{..} router = do
---   outputs <- unCompiler router
---   MC.exec @Sys.IO $ Sys.removePathForcibly compilerEnvDest
---   -- FIXME: use pipes
---   forM_ outputs $ \Output{..} -> do
---     let destPath =
---           ( List.intercalate "." $
---               encodePath outputPath :
---               ( if List.null outputExts
---                   then ["txt"]
---                   else Text.unpack . encodePathSegment <$> outputExts
---               )
---           )
---     -- hPutStrLn stderr $ "mkdir: " <> show (Sys.takeDirectory destPath)
---     MC.exec @Sys.IO $
---       Sys.createDirectoryIfMissing True $
---         compilerEnvDest Sys.</> Sys.takeDirectory destPath
---     -- hPutStrLn stderr $ "write: " <> show destPath
---     outputBSL <- outputData content
---     MC.exec @Sys.IO $
---       BSL.writeFile (compilerEnvDest Sys.</> destPath) $
---         outputBSL
+siteManifest :: Monad m => Compiler m a -> m [Sys.FilePath]
+siteManifest router = (outputPathFile . outputPathRelative <$>) <$> unCompiler router
 
-manifest :: forall m a. Monad m => Compiler m a -> m [Sys.FilePath]
-manifest router = do
+siteMap ::
+  Monad m =>
+  Compiler m a ->
+  (a --> m BSB.Builder) ->
+  m (Map.Map OutputPath (m BSB.Builder))
+siteMap router content = do
   outputs <- unCompiler router
-  return
-    [ destPath
-    | out <- outputs
-    , let destPath =
-            ( List.intercalate "." $
-                encodePath (outputPath out) :
-                ( if List.null (outputExts out)
-                    then ["txt"]
-                    else Text.unpack . encodePathSegment <$> outputExts out
-                )
-            )
-    ]
+  return $
+    Map.fromList
+      [ (outputPathRelative out, outputData out content)
+      | out <- outputs
+      ]
+
+-- ** Type 'CompilerEnv'
+data CompilerEnv = CompilerEnv
+  { compilerEnvDest :: Sys.FilePath
+  , -- , compilerEnvSource :: Sys.FilePath
+    compilerEnvIndex :: Sys.FilePath
+    -- , compilerEnvModel :: model
+    -- , compilerEnvPath :: [PathSegment]
+  }
+  deriving (Show)
 
 -- instance Applicative m => Applicative (Compiler m) where
 --   pure = Compiler . pure . pure . pure
@@ -150,277 +128,156 @@ instance Applicative m => Sym.ProductFunctor (Compiler m) where
   Compiler a <.> Compiler b = Compiler $ liftA2 (liftA2 (<.>)) a b
   Compiler a <. Compiler b = Compiler $ liftA2 (liftA2 (<.)) a b
   Compiler a .> Compiler b = Compiler $ liftA2 (liftA2 (.>)) a b
---instance Applicative m => Sym.AlternativeFunctor (Compiler m) where
+
+-- instance Applicative m => Sym.AlternativeFunctor (Compiler m) where
 --  Compiler a <|> Compiler b = Compiler (liftA2 (<>) a b)
+
 instance Applicative m => Sym.SumFunctor (Compiler m) where
   Compiler a <+> Compiler b = Compiler $ liftA2 (\as bs -> (a2e <$> as) <> (b2e <$> bs)) a b
     where
-    a2e :: Output a -> Output (Either a b)
-    a2e o = o{ outputData = outputData o . fst }
-    b2e :: Output b -> Output (Either a b)
-    b2e o = o{ outputData = outputData o . snd }
+      a2e :: Output a -> Output (Either a b)
+      a2e o = o{outputData = outputData o . fst}
+      b2e :: Output b -> Output (Either a b)
+      b2e o = o{outputData = outputData o . snd}
 
-instance (Applicative m, CompilerUnToF a) => Optionable a (Compiler m) where
-  optional (Compiler ma) = Compiler $ (\as -> (a2n <$> as) <> (a2j <$> as)) <$> ma
+instance (Applicative m, Sym.ToFable a) => Optionable a (Compiler m) where
+  optional (Compiler ma) = Compiler $ (\as -> forNothing : (forJust <$> as)) <$> ma
     where
-    a2n :: Output a -> Output (Maybe a)
-    a2n o = o{ outputData = ($ Nothing) }
-    a2j :: Output a -> Output (Maybe a)
-    a2j o = o{ outputData = \k -> outputData o $ compilerUnToF @(CompilerIsToF a) $ k . Just }
---   optional (Compiler ma) = Compiler $ (\as -> (a2n <$> as) <> (a2j <$> as)) <$> ma
+      forNothing :: Output (Maybe a)
+      forNothing = Output{outputPath = mempty, outputData = ($ Nothing)}
+      forJust :: Output a -> Output (Maybe a)
+      forJust o = o{outputData = \k -> outputData o $ Sym.tofOffun $ k . Just}
+
+instance Functor m => Sym.Voidable (Compiler m) where
+  void _a (Compiler ma) =
+    Compiler $
+      (\os -> (\o -> o{outputData = id}) <$> os) <$> ma
+
+--   optional (Compiler ma) = Compiler $ (\as -> forNothing : (forJust <$> as)) <$> ma
 --     --pure Nothing Sym.<|> (Just <$> ma)
 --     where
---     a2n :: Output a -> Output (Maybe a)
---     a2n o = o{ outputData = fst }
---     a2j :: Output a -> Output (Maybe a)
---     a2j o = o{ outputData = outputData o . snd }
---
--- ** Class 'CompilerUnToF'
-type CompilerUnToF a = CompilerUnToFIf (CompilerIsToF a) a
-class CompilerUnToFIf (t :: Bool) a where
-  compilerUnToF :: (a -> next) -> CompilerToFIf t a next
-instance CompilerUnToFIf 'True () where
-  compilerUnToF = ($ ())
-instance (CompilerUnToF a, CompilerUnToF b) => CompilerUnToFIf 'True (a, b) where
-  compilerUnToF ab2n = compilerUnToF @(CompilerIsToF a) $ \a -> compilerUnToF @(CompilerIsToF b) $ \b -> ab2n (a,b)
-instance (CompilerUnToF a, CompilerUnToF b) => CompilerUnToFIf 'True (Either a b) where
-  compilerUnToF e2n = ( compilerUnToF @(CompilerIsToF a) $ e2n . Left
-                      , compilerUnToF @(CompilerIsToF b) $ e2n . Right
-                      )
-instance CompilerUnToFIf 'False a where
-  compilerUnToF = id
+--     forNothing :: Output a -> Output (Maybe a)
+--     forNothing o = o{ outputData = fst }
+--     forJust :: Output a -> Output (Maybe a)
+--     forJust o = o{ outputData = outputData o . snd }
 
 instance
   ( Generic a
   , Sym.RepOfEoT a
   , sem ~ Compiler m
-  , CompilerIsToF a ~ 'False
-  , e ~ Sym.EoT (Sym.ADT a)
-  , CompilerUnToF e
+  , Sym.IsToF a ~ 'False
+  , eot ~ Sym.EoT (Sym.ADT a)
+  , Sym.ToFable eot
   , Functor m
-  ) => Dataable__ a (Compiler m) where
-  data__ :: sem (Sym.EoT (Sym.ADT a)) -> sem a
-  data__ (Compiler e) = Compiler ((data__ <$>) <$> e)
+  ) =>
+  Dataable a (Compiler m)
+  where
+  dataType :: sem (Sym.EoT (Sym.ADT a)) -> sem a
+  dataType (Compiler mos) = Compiler ((dataType <$>) <$> mos)
 instance
   ( Generic a
-  --, Sym.EoTOfRep a
   , Sym.RepOfEoT a
   , sem ~ Output
-  , CompilerIsToF a ~ 'False
-  --, CompilerIsToF eot ~ 'False
+  , Sym.IsToF a ~ 'False
   , eot ~ Sym.EoT (Sym.ADT a)
-  , CompilerUnToF eot
-  ) => Dataable__ a Output where
-  data__ :: sem (Sym.EoT (Sym.ADT a)) -> sem a
-  data__ o = o { outputData = \k -> (outputData o) $ compilerUnToF @(CompilerIsToF eot) $ k . Sym.adtOfeot }
+  , Sym.ToFable eot
+  ) =>
+  Dataable a Output
+  where
+  dataType :: sem (Sym.EoT (Sym.ADT a)) -> sem a
+  dataType o = o{outputData = \k -> (outputData o) $ Sym.tofOffun $ k . Sym.adtOfeot}
 instance Applicative m => PathSegmentable (Compiler m) where
-  pathSegment s = Compiler $ pure
-    [
-      Output
-        { outputPath = [s]
-        , outputExts = []
-        , outputData = id
-        }
-    ]
+  pathSegment s =
+    Compiler $
+      pure
+        [ Output
+            { outputPath =
+                OutputPath
+                  { outputPathSegs = [s]
+                  , outputPathExts = []
+                  }
+            , outputData = id
+            }
+        ]
 instance
-  ( Show a
-  , Monad m
+  ( Applicative m
   , n ~ m
-  , end ~ m BSL.ByteString
   , MimeTypes ts (MimeEncodable a)
   ) =>
-  Responsable a ts n end (Compiler m)
+  Responsable a ts n (Compiler m)
   where
-  response = Compiler $ pure $
-    ( \(_mediaType, MimeType (Proxy :: Proxy t)) ->
-        Output
-          { outputPath = []
-          , outputExts = [decodePathSegment (fileExtension @t)]
-          , outputData = \(Refl, Response ma) -> do
-              a <- ma
-              pure $ mimeEncode @_ @t a
-          }
-    )
-      <$> toList (mimeTypesMap @ts @(MimeEncodable a))
-
--- ** Type 'CompilerEnv'
-data CompilerEnv = CompilerEnv
-  { compilerEnvDest :: Sys.FilePath
-  , -- , compilerEnvSource :: Sys.FilePath
-    compilerEnvIndex :: Sys.FilePath
-    --, compilerEnvModel :: model
-    -- , compilerEnvPath :: [PathSegment]
-  }
-  deriving (Show)
+  response =
+    Compiler $
+      pure $
+        ( \(_mediaType, MimeType (Proxy :: Proxy t)) ->
+            Output
+              { outputPath =
+                  OutputPath
+                    { outputPathSegs = []
+                    , outputPathExts = [decodePathSegment (fileExtension @t)]
+                    }
+              , outputData = \(CompilerEndpoint Refl (Response ma)) ->
+                  mimeEncode @_ @t <$> ma
+              }
+        )
+          <$> toList (mimeTypesMap @ts @(MimeEncodable a))
 
 -- ** Type 'Output'
--- TODO: use Seq instead of []
+
 data Output a = Output
-  { outputPath :: [PathSegment]
-  , outputExts :: [PathSegment]
-  , outputData :: forall next. CompilerToF a next -> next
-  --, outputBSL :: BSL.ByteString
-  -- , outputType :: MimeType (MimeEncodable a)
+  { outputPath :: OutputPath
+  , outputData :: forall next. (a --> next) -> next
   }
 
--- instance Sym.SumFunctor Output where
---   a <+> b = Output
---     { outputPath = outputPath a <> outputPath b
---     , outputExts = outputExts a <> outputExts b
---     , outputData = \(a2n, b2n) -> outputData a a2n
---     }
-instance Sym.ProductFunctor Output where
-  a <.> b = Output
-    { outputPath = outputPath a <> outputPath b
-    , outputExts = outputExts a <> outputExts b
-    , outputData = outputData b . outputData a
-    }
-  a <. b = Output
-    { outputPath = outputPath a <> outputPath b
-    , outputExts = outputExts a <> outputExts b
-    , outputData = outputData b . outputData a
-    }
-  a .> b = Output
-    { outputPath = outputPath a <> outputPath b
-    , outputExts = outputExts a <> outputExts b
-    , outputData = outputData b . outputData a
-    }
---   deriving (Functor, Show)
--- instance Applicative Output where
---   pure a =
---     Output
---       { outputPath = []
---       , outputExts = []
---       , outputData = a
---       --, outputBSL = ""
---       -- , outputType = mediaType @PlainText
---       }
---   oa2b <*> oa =
---     Output
---       { outputPath = outputPath oa2b <> outputPath oa
---       , outputExts = outputExts oa2b <> outputExts oa
---       , outputData = outputData oa2b (outputData oa)
---       --, outputBSL = outputBSL oa2b <> outputBSL oa
---       }
+outputBuilder :: Output a -> (a --> m BSB.Builder) -> m BSB.Builder
+outputBuilder = outputData
 
+outputPathRelative :: Output a -> OutputPath
+outputPathRelative out
+  | List.null (outputPathExts outPath) = outPath{outputPathExts = ["txt"]}
+  | otherwise = outPath
+  where
+    outPath = outputPath out
 
--- * Type family 'CompilerToF'
-type CompilerToF a next = CompilerToFIf (CompilerIsToF a) a next
-type family CompilerToFIf t a next :: Type where
--- For '<.>': curry.
-  CompilerToFIf 'True (a, b) next = CompilerToF a (CompilerToF b next)
--- For '<+>', request both branches.
-  CompilerToFIf 'True (Either l r) next = (CompilerToF l next, CompilerToF r next)
-  --CompilerToFIf 'True (Maybe a) next = (CompilerToF () next, CompilerToF a next)
--- Useless to ask '()' as argument.
-  CompilerToFIf 'True () next = next
--- Enable a different return value for each function.
-  CompilerToFIf 'True (Sym.Endpoint end a) next = (next :~: end, a)
--- Everything else becomes a new argument.
-  CompilerToFIf 'False a next = a -> next
+-- *** Type 'OutputPath'
+data OutputPath = OutputPath
+  { outputPathSegs :: [PathSegment]
+  , outputPathExts :: [PathSegment]
+  }
+  deriving (Eq, Ord, Show)
 
+outputPathFile :: OutputPath -> Sys.FilePath
+outputPathFile outPath =
+  List.intercalate "." $
+    encodePath (outputPathSegs outPath)
+      : (Text.unpack . encodePathSegment <$> outputPathExts outPath)
 
--- | This 'Bool' is added to 'ToFIf' to avoid overlapping instances.
-type family CompilerIsToF a :: Bool where
-  CompilerIsToF () = 'True
-  CompilerIsToF (a, b) = 'True
-  CompilerIsToF (Either l r) = 'True
-  --CompilerIsToF (Maybe a) = 'True
-  CompilerIsToF (Sym.Endpoint end a) = 'True
-  CompilerIsToF a = 'False
+instance Semigroup OutputPath where
+  x <> y =
+    OutputPath
+      { outputPathSegs = outputPathSegs x <> outputPathSegs y
+      , outputPathExts = outputPathExts x <> outputPathExts y
+      }
+instance Monoid OutputPath where
+  mempty = OutputPath{outputPathSegs = [], outputPathExts = []}
 
+instance Sym.ProductFunctor Output where
+  a <.> b =
+    Output
+      { outputPath = outputPath a <> outputPath b
+      , outputData = outputData b . outputData a
+      }
+  a <. b =
+    Output
+      { outputPath = outputPath a <> outputPath b
+      , outputData = outputData b . outputData a
+      }
+  a .> b =
+    Output
+      { outputPath = outputPath a <> outputPath b
+      , outputData = outputData b . outputData a
+      }
 
--- -- pathSegments _ss = Compiler $
--- --   MT.ReaderT $ \s ->
--- --     -- TODO: assert Set.member s ss
--- --     lift $
--- --       MT.modify' $ \st ->
--- --         st{compilerStatePath = compilerStatePath st </> Text.unpack (encodePathSegment s)}
---
--- {-
--- instance
---   TypeError (
---     'Text "The instance (Capturable a Compiler)"
---     ':$$: 'Text "is disabled when compiling to a static Web site."
---     ':$$: 'Text "You can use (whenInterpreter @Compiler siteNotUsingCapturable siteUsingCapturable)"
---     ':$$: 'Text "to replace calls to any method of Capturable."
---   ) => Capturable a Compiler where
---   capturePathSegment = undefined
--- instance
---   TypeError (
---     'Text "The instance (Capturable a (Reader model Compiler))"
---     ':$$: 'Text "is disabled when compiling to a static Web site."
---     ':$$: 'Text "You can use (whenInterpreter @(Reader model Compiler) siteNotUsingCapturable siteUsingCapturable)"
---     ':$$: 'Text "to replace calls to any method of Capturable."
---   ) => Capturable a (Reader model Compiler) where
---   capturePathSegment = undefined
--- -}
---
--- -- choosePathSegments _s = Compiler $ MT.ReaderT $ \s -> return $ Endo (List.reverse s <>)
--- {-
--- instance Capturable Compiler where
---   type CapturableConstraint Compiler =
---   capturePathSegment _n = Compiler $ MT.ReaderT $ \s ->
---     lift $ MT.modify' $ \st ->
---       st{compilerStatePath = compilerStatePath st </> Text.unpack (encodePathSegment s)}
--- -}
--- {-
--- instance Copyable Compiler where
---   copy path = Compiler $
---     lift $
---       MT.ReaderT $ \env -> do
---         lift $ do
---           doesPathExist (compilerEnvSource env </> path) >>= \case
---             True -> do
---               Sys.hPutStrLn Sys.stderr $
---                 "staticCopy: "
---                   <> show
---                     ( (compilerEnvSource env </> path)
---                     , (compilerEnvDest env </> path)
---                     )
---               copyDirRecursively
---                 path
---                 (compilerEnvSource env </> path)
---                 (compilerEnvDest env)
---             False -> do
---               Sys.hPutStrLn Sys.stderr $ "error: path does not exist: " <> (compilerEnvSource env </> path)
--- instance Encodable fmt a => Contentable fmt a Compiler where
---   content = Compiler $
---     MT.ReaderT $ \a -> MT.ReaderT $ \env -> do
---       st <- MT.get
---       let destPath = compilerEnvDest env </> compilerStatePath st
---       lift $ do
---         -- Sys.hPutStrLn Sys.stderr $ "mkdir: " <> show (Sys.takeDirectory destPath)
---         createDirectoryIfMissing True (Sys.takeDirectory destPath)
---         -- Sys.hPutStrLn Sys.stderr $ "write: " <> show destPath
---         BSL.writeFile destPath $ encode @fmt a
--- -}
--- --instance Endable Compiler where
--- --  end = Compiler $ return $ Endo id
---
--- --pathSegments _cs = Compiler $ MT.ReaderT $ \s -> return $ Endo (s :)
--- -- instance Fileable Compiler where
--- --   type FileableConstraint Compiler = Typeable
--- --   static = Compiler $ MT.ReaderT $ \_a ->
--- --     return $ Endo (\x -> x)
---
--- {-
--- -- * The 'Compiler' interpreter
---
--- -- | Create files according to the given model of type 'a'.
--- newtype Compiler a = Compiler
---   { unCompiler :: [Comp a]
---   }
---   deriving (Show, Functor)
---
--- instance Applicative Compiler where
---   pure = Compiler . pure . pure
---   Compiler f <*> Compiler x = Compiler $ (<*>) <$> f <*> x
---
--- -- instance Monad Compiler where
--- --   return = pure
--- --   Compiler x >>= f = Compiler (x >>=)
---
 -- compile :: Show a => Renderable a => Compiler a -> CompilerEnv -> Sys.IO ()
 -- compile compiler conf@CompilerEnv{..} = do
 --   createDirectoryIfMissing True compilerEnvDest
@@ -453,120 +310,19 @@ type family CompilerIsToF a :: Bool where
 --                 Sys.hPutStrLn Sys.stderr $ "error: path does not exist: " <> (compilerEnvSource </> staticPath)
 --           -- log LevelWarn $ toText $ "? " <> staticPath <> " (missing)"
 --           Right bs -> do
---             let destPath = compilerEnvDest </> routePath
+--             let outputFullPath = compilerEnvDest </> routePath
 --                            {-
 --                            maybe (routePath </> compilerEnvIndex)
 --                                  (routePath Sys.FilePath.<.>)
 --                                  (compType comp)
 --                           -}
---             -- Sys.hPutStrLn Sys.stderr $ "mkdir: " <> show (Sys.takeDirectory destPath)
---             createDirectoryIfMissing True (Sys.takeDirectory destPath)
---             -- Sys.hPutStrLn Sys.stderr $ "write: " <> show destPath
---             BSL.writeFile destPath bs
---
--- -- ** Class 'Renderable'
--- class Renderable a where
---   render :: a -> Either Sys.FilePath BSL.ByteString
--- instance Renderable () where
---   render () =
---     --Left $ pathOfPathSegments compPathSegments
---     Right BSL.empty
---
--- -- ** Type 'Comp'
--- data Comp a = Comp
---   { compPathSegments :: [PathSegment] -- TODO: Endo? Seq?
---   , compData :: a
---   -- , compType :: MimeType (MimeEncodable a)
---   }
--- deriving instance Eq a => Eq (Comp a)
--- deriving instance Ord a => Ord (Comp a)
--- deriving instance Show a => Show (Comp a)
--- deriving instance Functor Comp
--- instance Applicative Comp where
---   pure compData =
---     Comp
---       { compPathSegments = []
---       , compData
---       -- , compType = mediaType @PlainText
---       }
---   f <*> x =
---     Comp
---       { compPathSegments = compPathSegments f <> compPathSegments x
---       , compData = compData f (compData x)
---       -- , compType = compType f <> compType x
---       }
---
--- instance IsoFunctor Compiler where
---   (<%>) Iso{..} = (a2b <$>)
--- instance ProductFunctor Compiler where
---   (<.>) = liftA2 (,)
---   (<.) = (<*)
---   (.>) = (*>)
--- instance SumFunctor Compiler where
---   x <+> y =
---     Compiler $
---       (<>)
---         ((Left <$>) <$> unCompiler x)
---         ((Right <$>) <$> unCompiler y)
--- instance Optionable Compiler where
---   optional x =
---     Compiler $
---       Comp { compPathSegments = []
---            , compData = Nothing
---            -- , compType = Nothing
---            } :
---       ((Just <$>) <$> unCompiler x)
--- instance PathSegmentable Compiler where
---   pathSegment s = Compiler
---     [
---       Comp
---         { compPathSegments = [s]
---         , compData = ()
---         -- , compType = PlainText
---         }
---     ]
---   pathSegments ss =
---     Compiler $
---       [ Comp{ compPathSegments = [s]
---             , compData = s
---             -- , compType = Nothing
---             }
---       | s <- toList ss
---       ]
--- instance ContentTypeable PlainText () Compiler where
---   contentType =
---     Compiler
---       [ Comp
---           { compPathSegments = []
---           , compData = ()
---           --, compType = mediaType @PlainText
---           }
---       ]
---
--- -- instance Repeatable Compiler where
--- --   many0 (Compiler x) =
--- --     Compiler $
--- --       ((\Comp{} -> Comp [] []) <$> x)
--- --         <> ((\(Comp s a) -> Comp s [a]) <$> x)
--- --         <> ((\(Comp s a) -> Comp (s <> s) [a, a]) <$> x)
--- --   many1 (Compiler x) =
--- --     Compiler $
--- --       ((\(Comp s a) -> Comp s [a]) <$> x)
--- --         <> ((\(Comp s a) -> Comp (s <> s) [a, a]) <$> x)
--- -- instance Endable Compiler where
--- --   end = Compiler [Comp [] ()]
--- -- instance Capturable Compiler where
--- --   capturePathSegment n = Compiler $ [Comp [n] n]
--- -- instance Constantable c Compiler where
--- --   constant = pure
--- -}
---
+--             -- Sys.hPutStrLn Sys.stderr $ "mkdir: " <> show (Sys.takeDirectory outputFullPath)
+--             createDirectoryIfMissing True (Sys.takeDirectory outputFullPath)
+--             -- Sys.hPutStrLn Sys.stderr $ "write: " <> show outputFullPath
+--             BSL.writeFile outputFullPath bs
+
 copyDirRecursively ::
-  ( --MonadIO m,
-    --MonadUnliftIO m,
-    --MonadLoggerIO m,
-    HasCallStack
-  ) =>
+  HasCallStack =>
   -- | Source file path relative to CWD
   Sys.FilePath ->
   -- | Absolute path to source file to copy.
@@ -577,21 +333,22 @@ copyDirRecursively ::
 copyDirRecursively srcRel srcAbs destParent = do
   Sys.doesFileExist srcAbs >>= \case
     True -> do
-      Sys.hPutStrLn Sys.stderr $ "copyDirRecursively: " <> show ("srcAbs is a file", srcAbs)
+      Sys.hPutStrLn Sys.stderr $ "copyDirRecursively: " <> show ("srcAbs is a file" :: Text, srcAbs)
       copyFileCreatingParents srcAbs (destParent Sys.</> srcRel)
     False ->
       Sys.doesDirectoryExist srcAbs >>= \case
         False -> do
-          Sys.hPutStrLn Sys.stderr $ "copyDirRecursively: " <> show ("srcAbs is neither a file nor directory", srcAbs)
+          Sys.hPutStrLn Sys.stderr $ "copyDirRecursively: " <> show ("srcAbs is neither a file nor directory" :: Text, srcAbs)
           return ()
         -- throw $ StaticAssetMissing srcAbs
         True -> do
-          Sys.hPutStrLn Sys.stderr $ "copyDirRecursively: " <> show ("srcAbs is a directory", srcAbs)
+          Sys.hPutStrLn Sys.stderr $ "copyDirRecursively: " <> show ("srcAbs is a directory" :: Text, srcAbs)
           Sys.createDirectoryIfMissing True (destParent Sys.</> srcRel)
           fs <- Sys.getDirectoryFiles srcAbs ["**"]
           forM_ fs $ \fp -> do
-            let a = srcAbs Sys.</> fp
-                b = destParent Sys.</> srcRel Sys.</> fp
+            let
+              a = srcAbs Sys.</> fp
+              b = destParent Sys.</> srcRel Sys.</> fp
             copyFileCreatingParents a b
   where
     copyFileCreatingParents a b = do