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)
16 import Data.Set qualified as Set
17 import Data.String (IsString (..))
18 import GHC.Generics (Generic)
19 import Text.Show (Show (..))
23 -- | 'dataType' can be used at any point where
24 -- the Tuples-of-Functions are no longer wanted.
27 <+> pathSegment "feed"
29 </> (dataType @(Maybe Lang) $ pathSegment "all" <+> infer)
30 <.> optional (capturePathSegment @Tag "tag")
35 -- (Either () (Either () (Maybe Lang, Maybe Tag)))
42 contentStatic = return "STATIC"
43 contentFeed = return "FEED"
44 contentFilter filterLang filterTag =
48 Nothing -> maybe "ALL-LANG-ALL-TAGS" show filterTag
49 Just lang -> case filterTag of
51 Just tag -> show (lang, tag)
53 -- c0 = compile CompilerEnv{} router content
55 address_static, address_feed :: Address
56 address_filter :: Maybe Lang -> Maybe (Captured Tag Addresser) -> Address
66 deriving (Eq, Show, Generic)
68 routeLang = dataType @Lang $ pathSegment "en" <+> pathSegment "fr"
70 -- | Using 'Inferable' has the downside of requiring
71 -- to explicit manually the symantices required.
72 instance (SumFunctor sem, PathSegmentable sem, Dataable Lang sem) => Inferable Lang sem where
76 newtype Tag = Tag {unTag :: PathSegment} deriving (Eq, Ord, Show)
77 instance IsString Tag where
78 fromString = Tag . fromString
80 -- | Capturing a 'Tag' makes no sense when compiling a static site.
81 -- Hence the 'Compiler' semantic for 'Capturable'
82 -- requires a readable 'Model' somewhere in the monad stack
83 -- in order to generate all 'Tag's folders.
84 instance MC.MonadReader Model m => Capturable Tag (Compiler m) where
85 capturePathSegment _n =
90 { outputPath = OutputPath{outputPathSegs = [unTag tag], outputPathExts = []}
91 , outputData = ($ tag)
93 | tag <- Set.toList (modelTags model)
96 instance Capturable Tag Addresser where
97 -- FIXME: check given tag exists?
98 capturePathSegment _n = Addresser \k t -> k (Address [unTag t])
102 { modelTags :: Set Tag
105 model1 = Model{modelTags = Set.fromList []}
106 model2 = Model{modelTags = Set.fromList ["cat1", "cat2", "cat3"]}