diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..1fecbc4a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,157 @@ +# AGENTS.md + +This file is for coding agents working in `floskell`. + +## Scope + +- Repository: `floskell`, a Haskell source formatter / pretty printer. +- Build systems present: `cabal` and `stack`. +- CI uses `cabal` on macOS and Linux, across multiple GHC versions. +- No Cursor rules were found in `.cursor/rules/`. +- No `.cursorrules` file was found. +- No Copilot instructions were found at `.github/copilot-instructions.md`. + +## Repository Layout + +- `src/Floskell*.hs`: library modules. +- `src/main/Main.hs`: CLI executable. +- `src/main/Test.hs`: Hspec test runner. +- `src/main/Benchmark.hs`: Criterion benchmarks. +- `src/main/Markdone.hs`: markdown parsing support used by tests and benches. +- `TEST.md`: canonical markdown-based regression input. +- `styles/*.md`: expected formatter output for each predefined style. +- `floskell.cabal`: authoritative target definitions and dependencies. +- `.github/workflows/ci.yml`: authoritative CI commands. + +## Preferred Workflow + +- Prefer `cabal` for build, test, and verification because CI uses it. +- Use `stack` only when you specifically need the repo's resolver workflow. +- Keep changes compatible with a broad GHC range; the codebase actively supports older compilers and multiple `haskell-src-exts` versions. +- Expect CPP guards around dependency and parser-version differences. + +## Build Commands + +- Build everything: `cabal build all` +- Build library only: `cabal build floskell` +- Build executable only: `cabal build exe:floskell` +- Build tests only: `cabal build test:floskell-test` +- Build benchmarks only: `cabal build bench:floskell-bench` +- Configure tests and benches explicitly: `cabal configure --enable-test --enable-benchmarks --disable-documentation` +- Check install plan without building: `cabal build --dry-run` +- Open a REPL for the library: `cabal repl floskell` + +## Lint / Static Checks + +- There is no dedicated linter config in the repo for `hlint`, `ormolu`, `fourmolu`, or `stylish-haskell`. +- The main static baseline is a warning-clean build with `-Wall` enabled in the Cabal targets. +- Treat `cabal build all` as the most important local lint check. +- Run Cabal package validation with `cabal check`. +- If you touch public metadata or dependencies, run both `cabal check` and `cabal build all`. + +## Test Commands + +- Run the full test suite: `cabal test all` +- Run only the main test suite target: `cabal test floskell-test` +- Run tests with direct output: `cabal test floskell-test --test-show-details=direct` +- Run benchmarks: `cabal bench floskell-bench` +- Run the executable on a file: `cabal run floskell -- path/to/File.hs` +- Run the executable on stdin: `cabal run floskell < path/to/File.hs` + +## Running A Single Test + +The test suite uses Hspec from `src/main/Test.hs`, so use Hspec's match filtering. + +- Run one example by exact or partial test name: + `cabal test floskell-test --test-show-details=direct --test-options='--match "Snippet 1"'` +- Run a narrower test: + `cabal test floskell-test --test-show-details=direct --test-options='--match "formats as expected"'` +- Run one section: + `cabal test floskell-test --test-show-details=direct --test-options='--match "ImportDecl"'` +- Stack equivalent: + `stack test --test-arguments='--match "Snippet 1"'` + +Notes: + +- Test names are generated from markdown sections plus snippet numbers. +- If you are unsure of the exact name, inspect `src/main/Test.hs` and `TEST.md` first. + +## High-Value Verification Paths + +- Formatter logic changed: run `cabal test floskell-test`. +- CLI behavior changed: run `cabal build exe:floskell` and at least one `cabal run floskell -- ...` smoke test. +- Config or JSON parsing changed: run `cabal test floskell-test` and exercise `--print-config`. +- Performance-sensitive pretty-printing changed: consider `cabal bench floskell-bench`. +- Packaging changed: run `cabal check`. + +## Test Architecture + +- Regression tests are markdown-driven. +- `TEST.md` is the canonical input corpus. +- Each file in `styles/*.md` stores the expected rendering for a predefined style. +- Many failures are easiest to diagnose by locating the referenced markdown section/snippet. + +## Source Style + +Follow the existing Haskell style in the repository rather than introducing a new formatter style. + +- Use 4-space indentation. +- Prefer hanging indentation for long signatures, records, and import lists. +- Preserve the import grouping style: standard/library imports, then local imports, separated by blank lines. +- Keep alignment conservative and readable; do not introduce decorative alignment that the surrounding file does not use. + +## Imports + +- Use explicit import lists for external modules when only a few names are needed. +- Use `qualified` imports for modules like `Data.Text`, `Data.Map.Strict`, and similar namespaces. +- Use short, conventional aliases already common in the codebase: `T`, `TL`, `TB`, `TIO`, `Map`, `M`, `JSON`, `PP`. +- Open imports are acceptable for internal modules when that is already the local convention. +- Keep imports sorted/grouped consistently with the surrounding file; avoid churn-only reorderings. + +## Language Pragmas And CPP + +- Keep pragmas file-local and minimal. +- Common pragmas here include `CPP`, `OverloadedStrings`, `RecordWildCards`, `LambdaCase`, and targeted feature flags. +- Preserve existing CPP compatibility guards. +- When changing parser- or dependency-sensitive code, check for version branches before simplifying. +- Prefer small, localized `#if` blocks over duplicating large amounts of logic unless parser compatibility requires it. + +## Types And Signatures + +- Give top-level functions explicit type signatures. +- Keep helper signatures when they clarify polymorphism, laziness/strictness, or error types. +- Use `newtype` when representing a single wrapped concept. +- Prefer records for configuration and state structures. +- Prefer record updates over positional reconstruction. + +## Naming + +- Modules, types, and constructors use `CamelCase`. +- Functions and values use `camelCase`. +- Record fields usually carry a domain prefix, e.g. `cfg*`, `ps*`, `style*`. +- Match existing terminology: `reformat`, `pretty`, `style`, `config`, `fixities`, `imports`, `comments`. + +## Error Handling + +- In library-style code, prefer returning `Either String a` or `Maybe a` for expected failures. +- Keep pure formatting/parsing paths explicit about failure, as `reformat` already does. +- It is acceptable to keep `error` for test-only code and genuinely impossible internal states if the surrounding module already uses that pattern. +- IO boundary code may catch and rethrow exceptions when handling filesystem edge cases, as in `src/main/Main.hs`. + +## Comments And Documentation + +- Use Haddock-style module or declaration comments for exported APIs and non-obvious internals. +- Preserve carefully placed comments in tests and markdown fixtures; they are often part of regression coverage. + +## Testing Conventions + +- If you change formatter behavior, expect corresponding updates to style reference outputs. +- Prefer minimal changes to `TEST.md` and `styles/*.md`; broad fixture churn is hard to review. +- Test descriptions are generated, so clear section headings in markdown matter. + +## Agent-Specific Guidance + +- Before editing, inspect the target file's surrounding style and match it. +- Avoid repo-wide formatting passes; this project is intentionally style-sensitive. +- Keep diffs small in generated reference markdown unless the behavior change truly affects many styles. +- When in doubt, trust `floskell.cabal`, `src/main/Test.hs`, `TEST.md`, and `.github/workflows/ci.yml` over assumptions. diff --git a/TEST.md b/TEST.md index 63eeb232..7421dcdc 100644 --- a/TEST.md +++ b/TEST.md @@ -153,12 +153,19 @@ module Main {-# WARNING "do not use" #-} where import Prelude import Data.Text (Text) import qualified Data.Text as T +import Data.Text qualified as Text import qualified Data.ByteString (ByteString,pack,unpack) import qualified Data.ByteString as BS (pack, unpack) import Control.Monad hiding (forM) import {-# SOURCE #-} safe qualified "foo" Foo as F ``` +``` haskell +import Prelude +import Data.Text (Text) +import Control.Monad hiding (forM) +``` + ## Decl ### TypeDecl diff --git a/src/Floskell.hs b/src/Floskell.hs index e3ae1c91..887de446 100644 --- a/src/Floskell.hs +++ b/src/Floskell.hs @@ -24,11 +24,13 @@ module Floskell , defaultExtensions ) where +import Control.Monad ( guard ) import Data.List import Data.Maybe #if __GLASGOW_HASKELL__ <= 802 import Data.Monoid #endif +import Data.Char ( isSpace ) import Data.Text.Lazy ( Text ) import qualified Data.Text.Lazy as TL @@ -162,7 +164,7 @@ reformatBlock mode config (lines, cpp) = ParseFailed loc e -> Left $ Exts.prettyPrint (loc { srcLine = srcLine loc }) ++ ": " ++ e where - code = TL.unpack $ TL.intercalate "\n" lines + code = TL.unpack $ TL.intercalate "\n" $ map rewriteImportQualifiedPost lines makeComment (Exts.Comment inline span text) = Comment (if inline then InlineComment else LineComment) span text @@ -174,6 +176,84 @@ reformatBlock mode config (lines, cpp) = then x : mergeComments xs' ys else y : mergeComments xs ys' +rewriteImportQualifiedPost :: Text -> Text +rewriteImportQualifiedPost = TL.pack . rewriteImportQualifiedPostString . TL.unpack + +rewriteImportQualifiedPostString :: String -> String +rewriteImportQualifiedPostString line = case findPostQualifiedImport line of + Just (moduleToken, qualifiedToken) -> + swapTokens moduleToken qualifiedToken line + Nothing -> line + +findPostQualifiedImport :: String -> Maybe (ImportToken, ImportToken) +findPostQualifiedImport line = do + let tokens = tokenize line + (importToken, rest) <- uncons tokens + guard $ tokenText importToken == "import" + let rest' = skipImportModifiers rest + (moduleToken, afterModule) <- uncons rest' + qualifiedToken <- listToMaybe afterModule + guard $ tokenText qualifiedToken == "qualified" + return (moduleToken, qualifiedToken) + +skipImportModifiers :: [ImportToken] -> [ImportToken] +skipImportModifiers + ( ImportToken _ _ "{-#" + : ImportToken _ _ "SOURCE" + : ImportToken _ _ "#-}" + : xs + ) = + skipImportModifiers xs +skipImportModifiers (tok : xs) + | tokenText tok == "safe" = skipImportModifiers xs + | isPackageToken tok = skipImportModifiers xs +skipImportModifiers xs = xs + +isPackageToken :: ImportToken -> Bool +isPackageToken tok = case tokenText tok of + '"' : _ -> True + _ -> False + +swapTokens :: ImportToken -> ImportToken -> String -> String +swapTokens moduleToken qualifiedToken line = + prefix ++ tokenText qualifiedToken ++ middle ++ tokenText moduleToken ++ suffix + where + prefix = take (tokenStart moduleToken) line + middle = take (tokenStart qualifiedToken - tokenEnd moduleToken) + $ drop (tokenEnd moduleToken) line + suffix = drop (tokenEnd qualifiedToken) line + +data ImportToken = ImportToken + { tokenStart :: Int + , tokenEnd :: Int + , tokenText :: String + } + +tokenize :: String -> [ImportToken] +tokenize = go 0 + where + go _ [] = [] + go i xs@(x : xs') + | isSpace x = go (i + 1) xs' + | x == '"' = + let (tok, rest) = spanString xs + len = length tok + in + ImportToken i (i + len) tok : go (i + len) rest + | otherwise = + let (tok, rest) = break isSpace xs + len = length tok + in + ImportToken i (i + len) tok : go (i + len) rest + + spanString [] = ([], []) + spanString (x : xs) = firstChar [x] xs + + firstChar acc [] = (reverse acc, []) + firstChar acc (x : xs) + | x == '"' = (reverse (x : acc), xs) + | otherwise = firstChar (x : acc) xs + prettyPrint :: Printer a -> Config -> Maybe Text prettyPrint printer = fmap (Buffer.toLazyText . psBuffer . snd) . execPrinter printer . initialPrintState diff --git a/src/Floskell/ConfigFile.hs b/src/Floskell/ConfigFile.hs index 49e593f8..64e03926 100644 --- a/src/Floskell/ConfigFile.hs +++ b/src/Floskell/ConfigFile.hs @@ -33,7 +33,7 @@ import qualified Data.Aeson.Types as JSON ( typeMismatch ) import qualified Data.Attoparsec.ByteString as AP import qualified Data.ByteString as BS import Data.Char ( isLetter, isSpace ) -import Data.List ( inits ) +import Data.List ( (\\), inits ) import qualified Data.Text as T import Floskell.Attoparsec ( parseOnly ) @@ -42,8 +42,9 @@ import Floskell.Styles ( Style(..), styles ) import GHC.Generics ( Generic ) import Language.Haskell.Exts - ( Extension(..), Fixity(..), Language(..), classifyExtension - , classifyLanguage ) + ( Extension(..), Fixity(..), KnownExtension(..) + , Language(..), classifyExtension, classifyLanguage + , knownExtensions ) import qualified Language.Haskell.Exts as HSE import System.Directory @@ -83,7 +84,8 @@ instance FromJSON AppConfig where language <- maybe (appLanguage defaultAppConfig) lookupLanguage <$> o .:? "language" extensions <- maybe (appExtensions defaultAppConfig) - (map lookupExtension) <$> o .:? "extensions" + ((appExtensions defaultAppConfig ++) . map lookupExtension) + <$> o .:? "extensions" fixities <- maybe (appFixities defaultAppConfig) (map lookupFixity) <$> o .:? "fixities" let fmt = styleConfig style @@ -105,7 +107,24 @@ instance FromJSON AppConfig where -- | Default program configuration. defaultAppConfig :: AppConfig -defaultAppConfig = AppConfig (head styles) Haskell2010 [] [] +defaultAppConfig = AppConfig (head styles) Haskell2010 defaultExtensions [] + +defaultExtensions :: [Extension] +defaultExtensions = [ e | e@EnableExtension{} <- knownExtensions ] + \\ map EnableExtension badExtensions + +badExtensions :: [KnownExtension] +badExtensions = + [ Arrows -- steals proc + , TransformListComp -- steals the group keyword + , XmlSyntax + , RegularPatterns -- steals a-b + , UnboxedTuples -- breaks (#) lens operator + , PatternSynonyms -- steals the pattern keyword + , RecursiveDo -- steals the rec keyword + , DoRec -- same + , TypeApplications -- since GHC 8 and haskell-src-exts-1.19 + ] -- | Show name of a style. showStyle :: Style -> String @@ -148,6 +167,8 @@ lookupLanguage name = case classifyLanguage name of -- | Lookup an extension by name. lookupExtension :: String -> Extension +lookupExtension "ImportQualifiedPost" = UnknownExtension "ImportQualifiedPost" +lookupExtension "NoImportQualifiedPost" = UnknownExtension "NoImportQualifiedPost" lookupExtension name = case classifyExtension name of UnknownExtension _ -> error $ "Unkown extension: " ++ name x -> x diff --git a/src/Floskell/Pretty.hs b/src/Floskell/Pretty.hs index 72fb4481..966e9e74 100644 --- a/src/Floskell/Pretty.hs +++ b/src/Floskell/Pretty.hs @@ -111,7 +111,7 @@ prettyOnside ast = do if nl then do printCommentsBefore True ast - onside $ prettyPrint ast + onside $ cut $ prettyPrint ast printCommentsAfter ast else onside $ pretty ast @@ -414,7 +414,9 @@ measure' :: Printer a -> Printer (Maybe [Int]) measure' p = fmap (: []) <$> measure p measureMatch :: Match NodeInfo -> Printer (Maybe [Int]) -measureMatch (Match _ name pats _ Nothing) = measure' (prettyApp name pats) +measureMatch (Match _ name pats rhs _) = case rhs of + UnGuardedRhs _ _ -> measure' (prettyApp name pats) + GuardedRhss _ grhss -> fmap sequence (mapM measureGuardedRhs grhss) measureMatch (InfixMatch _ pat name pats _ Nothing) = measure' go where go = do @@ -426,6 +428,12 @@ measureMatch (InfixMatch _ pat name pats _ Nothing) = measure' go inter spaceOrNewline $ map pretty pats measureMatch _ = return Nothing +measureGuardedRhs :: GuardedRhs NodeInfo -> Printer (Maybe Int) +measureGuardedRhs (GuardedRhs _ stmts _) = measure $ + withIndentConfig cfgIndentMultiIf (space >> aligned p) (flip indented p) + where + p = prettyGuard stmts + measureDecl :: Decl NodeInfo -> Printer (Maybe [Int]) measureDecl (PatBind _ pat _ Nothing) = measure' (pretty pat) measureDecl (FunBind _ matches) = @@ -495,7 +503,10 @@ prettyImports is = do alignModuleP <- getConfig (cfgAlignImportModule . cfgAlign) alignSpecP <- getConfig (cfgAlignImportSpec . cfgAlign) let maxNameLength = maximum $ map (length . moduleName . importModule) is - alignModule = if alignModuleP then Just 16 else Nothing + hasQualifiedImport = any importQualified is + alignModule = if alignModuleP && hasQualifiedImport + then Just 16 + else Nothing alignSpec = if alignSpecP then Just (fromMaybe 0 alignModule + 1 + maxNameLength) else Nothing @@ -712,6 +723,16 @@ prettyBinds binds = withIndentBy cfgIndentWhere $ do write "where" withIndent cfgIndentWhereBinds $ pretty binds +prettyGuard :: [Stmt NodeInfo] -> Printer () +prettyGuard stmts = do + operatorSectionR Pattern "|" $ write "|" + withLayout cfgLayoutDeclaration flex vertical + where + flex = listAutoWrap' pat sep stmts + vertical = list' pat sep stmts + pat = Pattern + sep = "," + instance Pretty Module where prettyPrint (Module _ mhead pragmas imports decls) = inter blankline $ catMaybes [ ifNotEmpty prettyPragmas pragmas @@ -1294,20 +1315,14 @@ instance Pretty Rhs where withIndent cfgIndentMultiIf $ linedOnside guardedrhss instance Pretty GuardedRhs where - prettyPrint (GuardedRhs _ stmts expr) = - withLayout cfgLayoutDeclaration flex vertical + prettyPrint (GuardedRhs _ stmts expr) = do + prettyGuard stmts + atTabStop stopRhs + withLayout cfgLayoutDeclaration (operator d op) (operatorV d op) + pretty expr where - flex = do - operatorSectionR Pattern "|" $ write "|" - listAutoWrap' Pattern "," stmts - operator Declaration "=" - pretty expr - - vertical = do - operatorSectionR Pattern "|" $ write "|" - list' Pattern "," stmts - operatorV Declaration "=" - pretty expr + d = Declaration + op = "=" instance Pretty Context where prettyPrint (CxSingle _ asst) = do diff --git a/src/Floskell/Printers.hs b/src/Floskell/Printers.hs index e24d535c..63d026aa 100644 --- a/src/Floskell/Printers.hs +++ b/src/Floskell/Printers.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Floskell.Printers @@ -65,7 +66,9 @@ import Control.Monad.State.Strict ( get, gets, modify ) import Data.List ( intersperse ) import qualified Data.Map.Strict as Map +#if __GLASGOW_HASKELL__ <= 802 import Data.Monoid ( (<>) ) +#endif import Data.Text ( Text ) import qualified Data.Text as T diff --git a/src/main/Main.hs b/src/main/Main.hs index da2efbd6..427d85b9 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -11,7 +11,6 @@ import qualified Data.Aeson.Encode.Pretty as JSON ( encodePretty ) import qualified Data.ByteString.Lazy as BL import Data.List ( sort ) import Data.Maybe ( isJust ) -import Data.Monoid ( (<>) ) import qualified Data.Text as T import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.IO as TIO @@ -39,12 +38,12 @@ import Options.Applicative import Paths_floskell ( version ) import System.Directory - ( copyFile, copyPermissions, getTemporaryDirectory, removeFile - , renameFile ) + ( copyFile, copyPermissions, getTemporaryDirectory, removeFile + , renameFile ) import System.IO - ( FilePath, hClose, hFlush, openTempFile, stdout ) + ( hClose, hFlush, openTempFile, stdout ) -import qualified Text.PrettyPrint.ANSI.Leijen as PP +import qualified Options.Applicative.Help.Pretty as PP -- | Program options. data Options = Options { optStyle :: Maybe String @@ -70,18 +69,19 @@ main = do Nothing -> return defaultAppConfig let config = mergeAppConfig baseConfig opts if optPrintFixities opts - then PP.displayIO stdout . PP.renderPretty 1.0 80 $ - docFixities packageFixities <> PP.linebreak + then PP.hPutDoc stdout $ docFixities packageFixities <> PP.hardline else if optPrintConfig opts then BL.putStr $ JSON.encodePretty config else run config (optFiles opts) where parser = info (helper <*> versioner <*> options) - (fullDesc - <> progDesc "Floskell reformats one or more Haskell modules." - <> header "floskell - A Haskell Source Code Pretty Printer" - <> footerDoc (Just (footerStyles PP.<$$> footerLanguages - PP.<$$> footerExtensions))) + (fullDesc + <> progDesc "Floskell reformats one or more Haskell modules." + <> header "floskell - A Haskell Source Code Pretty Printer" + <> footerDoc (Just (PP.vsep [ footerStyles + , footerLanguages + , footerExtensions + ]))) versioner = abortOption (InfoMsg $ "floskell " ++ showVersion version) (long "version" @@ -120,17 +120,23 @@ main = do makeFooter "Supported extensions:" [ show e | EnableExtension e <- knownExtensions ] + makeFooter :: String -> [String] -> PP.Doc makeFooter hdr xs = - PP.empty PP.<$$> PP.text hdr PP.<$$> (PP.indent 2 . PP.fillSep - . PP.punctuate PP.comma - . map PP.text $ sort xs) + PP.vsep [ PP.emptyDoc + , PP.pretty hdr + , PP.indent 2 . PP.fillSep . PP.punctuate PP.comma + . map PP.pretty $ sort xs + ] - docFixities = PP.vcat . PP.punctuate PP.linebreak + docFixities = PP.vcat . PP.punctuate PP.hardline . map (uncurry docPackageFixities) - docPackageFixities p fs = PP.text (p ++ ":") - PP.<$$> (PP.indent 2 . PP.fillSep . PP.punctuate PP.comma - . map (PP.text . showFixity) $ sort fs) + docPackageFixities p fs = PP.vsep + [ PP.pretty (p ++ ":") + , PP.indent 2 . PP.fillSep . PP.punctuate PP.comma + . map (PP.pretty . showFixity) $ sort fs + ] + -- | Reformat files or stdin based on provided configuration. run :: AppConfig -> [FilePath] -> IO () diff --git a/src/main/Markdone.hs b/src/main/Markdone.hs index 5b583cf6..5b5cb7e8 100644 --- a/src/main/Markdone.hs +++ b/src/main/Markdone.hs @@ -14,11 +14,9 @@ import Control.DeepSeq import Control.Monad.Catch import Data.Char -import Data.Monoid ( (<>) ) import Data.Text.Lazy ( Text ) import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Builder as TB -import qualified Data.Text.Lazy.IO as TIO import Data.Typeable import GHC.Generics diff --git a/styles/base.md b/styles/base.md index 25a23c46..50e62230 100644 --- a/styles/base.md +++ b/styles/base.md @@ -157,12 +157,19 @@ module Main {-# WARNING "do not use" #-} where import Prelude import Data.Text ( Text ) import qualified Data.Text as T +import qualified Data.Text as Text import qualified Data.ByteString ( ByteString, pack, unpack ) import qualified Data.ByteString as BS ( pack, unpack ) import Control.Monad hiding ( forM ) import {-# SOURCE #-} safe qualified "foo" Foo as F ``` +``` haskell +import Prelude +import Data.Text ( Text ) +import Control.Monad hiding ( forM ) +``` + ## Decl ### TypeDecl diff --git a/styles/chris-done.md b/styles/chris-done.md index 8801e3cd..96659546 100644 --- a/styles/chris-done.md +++ b/styles/chris-done.md @@ -177,12 +177,19 @@ module Main {-# WARNING "do not use" #-} where import Prelude import Data.Text (Text) import qualified Data.Text as T +import qualified Data.Text as Text import qualified Data.ByteString (ByteString,pack,unpack) import qualified Data.ByteString as BS (pack,unpack) import Control.Monad hiding (forM) import {-# SOURCE #-} safe qualified "foo" Foo as F ``` +``` haskell +import Prelude +import Data.Text (Text) +import Control.Monad hiding (forM) +``` + ## Decl ### TypeDecl diff --git a/styles/cramer.md b/styles/cramer.md index 877bc4a8..0541dcaa 100644 --- a/styles/cramer.md +++ b/styles/cramer.md @@ -168,12 +168,21 @@ import qualified Data.ByteString ( ByteString, pack, unpack ) import qualified Data.ByteString as BS ( pack, unpack ) import Data.Text ( Text ) import qualified Data.Text as T +import qualified Data.Text as Text import {-# SOURCE #-} safe qualified "foo" Foo as F import Prelude ``` +``` haskell +import Control.Monad hiding ( forM ) + +import Data.Text ( Text ) + +import Prelude +``` + ## Decl ### TypeDecl @@ -1041,7 +1050,7 @@ Ignore shebang lines module Main where - import Shower + import Shower main :: IO () main = printer "Hello" diff --git a/styles/gibiansky.md b/styles/gibiansky.md index edff642b..74788f5d 100644 --- a/styles/gibiansky.md +++ b/styles/gibiansky.md @@ -167,12 +167,19 @@ module Main {-# WARNING "do not use" #-} where import Prelude import Data.Text (Text) import qualified Data.Text as T +import qualified Data.Text as Text import qualified Data.ByteString (ByteString, pack, unpack) import qualified Data.ByteString as BS (pack, unpack) import Control.Monad hiding (forM) import {-# SOURCE #-} safe qualified "foo" Foo as F ``` +``` haskell +import Prelude +import Data.Text (Text) +import Control.Monad hiding (forM) +``` + ## Decl ### TypeDecl @@ -1032,7 +1039,7 @@ Ignore shebang lines module Main where - import Shower + import Shower main :: IO () main = printer "Hello" diff --git a/styles/johan-tibell.md b/styles/johan-tibell.md index 0532f561..44a3f872 100644 --- a/styles/johan-tibell.md +++ b/styles/johan-tibell.md @@ -181,12 +181,19 @@ module Main {-# WARNING "do not use" #-} where import Prelude import Data.Text (Text) import qualified Data.Text as T +import qualified Data.Text as Text import qualified Data.ByteString (ByteString,pack,unpack) import qualified Data.ByteString as BS (pack,unpack) import Control.Monad hiding (forM) import {-# SOURCE #-} safe qualified "foo" Foo as F ``` +``` haskell +import Prelude +import Data.Text (Text) +import Control.Monad hiding (forM) +``` + ## Decl ### TypeDecl