1 {-# LANGUAGE DeriveGeneric #-}
3 {-# LANGUAGE UndecidableInstances #-}
4 {-# LANGUAGE NoMonomorphismRestriction #-}
5 {-# OPTIONS_GHC -Wno-missing-signatures #-}
7 module Examples.Ex03 where
9 import Control.Monad (Monad (..))
10 import Control.Monad.Classes qualified as MC
12 import Data.Function (($), (.))
13 import Data.Maybe (Maybe (..), maybe)
14 import Data.Monoid (Monoid (..))
17 import Data.Set qualified as Set
18 import Data.String (IsString (..))
19 import GHC.Generics (Generic)
20 import Text.Show (Show (..))
24 -- | 'dataType' can be used at any point where
25 -- the Tuples-of-Functions are no longer wanted.
28 <+> pathSegment "feed"
30 </> (dataType @(Maybe Lang) $ pathSegment "all" <+> infer)
31 <.> optional (capturePathSegment @Tag "tag")
36 -- (Either () (Either () (Maybe Lang, Maybe Tag)))
43 contentStatic = return "STATIC"
44 contentFeed = return "FEED"
45 contentFilter filterLang filterTag =
49 Nothing -> maybe "ALL-LANG-ALL-TAGS" show filterTag
50 Just lang -> case filterTag of
52 Just tag -> show (lang, tag)
54 -- c0 = compile CompilerEnv{} router content
56 address_static, address_feed :: Address
57 address_filter :: Maybe Lang -> Maybe (Captured Tag Addresser) -> Address
67 deriving (Eq, Show, Generic)
69 routeLang = dataType @Lang $ pathSegment "en" <+> pathSegment "fr"
71 -- | Using 'Inferable' has the downside of requiring
72 -- to explicit manually the symantices required.
73 instance (SumFunctor sem, PathSegmentable sem, Dataable Lang sem) => Inferable Lang sem where
77 newtype Tag = Tag {unTag :: PathSegment} deriving (Eq, Ord, Show)
78 instance IsString Tag where
79 fromString = Tag . fromString
81 -- | Capturing a 'Tag' makes no sense when compiling a static site.
82 -- Hence the 'Compiler' semantic for 'Capturable'
83 -- requires a readable 'Model' somewhere in the monad stack
84 -- in order to generate all 'Tag's folders.
85 instance MC.MonadReader Model m => Capturable Tag (Compiler m) where
86 capturePathSegment _n =
91 { outputPath = OutputPath{outputPathSegs = [unTag tag], outputPathExts = []}
92 , outputData = ($ tag)
95 | tag <- Set.toList (modelTags model)
98 instance Capturable Tag Addresser where
99 -- FIXME: check given tag exists?
100 capturePathSegment _n = Addresser \k t ->
101 k Address{addressSegs = [unTag t], addressExts = []}
105 { modelTags :: Set Tag
108 model1 = Model{modelTags = Set.fromList []}
109 model2 = Model{modelTags = Set.fromList ["cat1", "cat2", "cat3"]}