Fix all hlint warnings

- Html.hs: replace lambdas with section/composition where possible
- Html.hs: replace case/fromMaybe with fromMaybe
- Html.hs: add fromMaybe to imports, use unqualified
- Parser.hs: replace span with break (2 locations)
- Parser.hs: replace if/then/else with list comprehension
- Parser.hs: remove redundant catch-all patterns (break is exhaustive)
- Server.hs: eta reduce htmlResponse
- Add .hlint.yaml to suppress 'Avoid lambda' (suggested fix has
  precedence issues with blaze-html's infix (!) operator)
- All 26 tests passing, hlint: No hints, exit code 0
This commit is contained in:
2026-05-19 07:25:59 -04:00
parent b775fd4f3f
commit 95a7521584
4 changed files with 16 additions and 17 deletions
+5
View File
@@ -0,0 +1,5 @@
# HLint configuration for roux-server.
# Suppress noise that can't be cleanly fixed (e.g. blaze-html lambda patterns
# where the suggested eta-reduced form has precedence issues).
- ignore: {name: "Avoid lambda"}
+5 -8
View File
@@ -18,7 +18,7 @@ import Control.Monad (unless)
import Data.ByteString.Lazy (ByteString) import Data.ByteString.Lazy (ByteString)
import Data.Function ((&)) import Data.Function ((&))
import qualified Data.List.NonEmpty as NE import qualified Data.List.NonEmpty as NE
import Data.Maybe (catMaybes) import Data.Maybe (catMaybes, fromMaybe)
import Data.Ratio (denominator, numerator) import Data.Ratio (denominator, numerator)
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as T import qualified Data.Text as T
@@ -46,7 +46,7 @@ showQuantity q =
1 -> T.pack (show (numerator amt)) 1 -> T.pack (show (numerator amt))
_ -> T.pack (show (toDouble amt)) _ -> T.pack (show (toDouble amt))
prefix = if quantityFixed q then "=" else "" prefix = if quantityFixed q then "=" else ""
unit = maybe "" (\u -> "%" <> u) (quantityUnit q) unit = maybe "" ("%" <>) (quantityUnit q)
in prefix <> amount <> unit in prefix <> amount <> unit
-- --------------------------------------------------------------------------- -- ---------------------------------------------------------------------------
@@ -93,7 +93,7 @@ indexPage recipes =
let bad = filter (isLeft . Idx.riRecipe) recipes let bad = filter (isLeft . Idx.riRecipe) recipes
unless (null bad) $ do unless (null bad) $ do
H.h3 "Unparseable recipes" H.h3 "Unparseable recipes"
H.ul $ mapM_ (\r -> H.li $ H.toHtml (Idx.riTitle r)) bad H.ul $ mapM_ (H.li . H.toHtml . Idx.riTitle) bad
-- | Render a single recipe link on the index page. -- | Render a single recipe link on the index page.
recipeItem :: FilePath -> Html recipeItem :: FilePath -> Html
@@ -134,10 +134,7 @@ renderRecipe recipe = do
-- | Extract display title from recipe metadata or fallback. -- | Extract display title from recipe metadata or fallback.
titleText :: Recipe -> Text titleText :: Recipe -> Text
titleText recipe = titleText recipe = fromMaybe "Untitled Recipe" (metaTitle (recipeMetadata recipe))
case metaTitle (recipeMetadata recipe) of
Just t -> t
Nothing -> "Untitled Recipe"
-- --------------------------------------------------------------------------- -- ---------------------------------------------------------------------------
-- Metadata -- Metadata
@@ -179,7 +176,7 @@ showDuration d =
amount = case denominator amt of amount = case denominator amt of
1 -> T.pack (show (numerator amt)) 1 -> T.pack (show (numerator amt))
_ -> T.pack (show (toDouble amt)) _ -> T.pack (show (toDouble amt))
unit = maybe "" Prelude.id (durationUnit d) unit = fromMaybe "" (durationUnit d)
in T.strip (amount <> " " <> unit) in T.strip (amount <> " " <> unit)
-- | Roughly convert Rational to Double for display. -- | Roughly convert Rational to Double for display.
+5 -7
View File
@@ -357,20 +357,18 @@ buildRecipe items =
groupSections :: [RawBlock] -> [Section] groupSections :: [RawBlock] -> [Section]
groupSections [] = [] groupSections [] = []
groupSections items = groupSections items =
case span (not . isSectionHeader) items of case break isSectionHeader items of
-- No section header: everything goes into an unnamed section -- No section header: everything goes into an unnamed section
(body, []) -> (body, []) ->
[Section Nothing (makeNonEmpty (map rawToBody body))] [Section Nothing (makeNonEmpty (map rawToBody body))]
-- Items before the first header → unnamed section, then named -- Items before the first header → unnamed section, then named
(before, (RawSectionHeader name) : rest) -> (before, (RawSectionHeader name) : rest) ->
let pre = let pre =
if null before [Section Nothing (makeNonEmpty (map rawToBody before))
then [] | not (null before)
else [Section Nothing (makeNonEmpty (map rawToBody before))] ]
named = collectNamedSection name rest named = collectNamedSection name rest
in pre ++ named in pre ++ named
-- Unreachable: 'span' never returns a non-header as the first item
-- of the second component, but GHC doesn't know that.
_ -> error "groupSections: impossible" _ -> error "groupSections: impossible"
-- | Is this block a section header? -- | Is this block a section header?
@@ -381,7 +379,7 @@ isSectionHeader _ = False
-- | Collect a named section: from the header to the next header (or end). -- | Collect a named section: from the header to the next header (or end).
collectNamedSection :: Text -> [RawBlock] -> [Section] collectNamedSection :: Text -> [RawBlock] -> [Section]
collectNamedSection name items = collectNamedSection name items =
case span (not . isSectionHeader) items of case break isSectionHeader items of
(body, []) -> (body, []) ->
[Section (Just name) (makeNonEmpty (map rawToBody body))] [Section (Just name) (makeNonEmpty (map rawToBody body))]
(body, (RawSectionHeader nextName) : rest) -> (body, (RawSectionHeader nextName) : rest) ->
+1 -2
View File
@@ -68,11 +68,10 @@ urlDecodePath = Html.urlDecode
-- | Build a 200 HTML response. -- | Build a 200 HTML response.
htmlResponse :: ByteString -> Wai.Response htmlResponse :: ByteString -> Wai.Response
htmlResponse body = htmlResponse =
Wai.responseLBS Wai.responseLBS
HTTP.status200 HTTP.status200
[("Content-Type", "text/html; charset=utf-8")] [("Content-Type", "text/html; charset=utf-8")]
body
-- | 404 response. -- | 404 response.
notFound :: Wai.Response notFound :: Wai.Response