### Deque Operations in Haskell Source: https://context7.com/commercialhaskell/rio/llms.txt Demonstrates the usage of the Deque type for efficient, mutable double-ended queues. Supports O(1) push/pop operations on both ends and can be used with unboxed, storable, and boxed vectors. Includes examples for creating, manipulating, and converting deques. ```haskell {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TypeApplications #-) import RIO import RIO.Deque import qualified RIO.Vector.Unboxed as U import qualified RIO.Vector.Boxed as B main :: IO () main = runSimpleApp $ do -- Create an unboxed deque for Ints (most efficient for primitives) intDeque <- newDeque @U.MVector @Int -- Push to front and back pushFrontDeque intDeque 1 pushFrontDeque intDeque 2 pushBackDeque intDeque 3 pushBackDeque intDeque 4 -- Deque now contains: [2, 1, 3, 4] -- Get size size <- getDequeSize intDeque logInfo $ "Deque size: " <> display size -- 4 -- Pop from front and back front <- popFrontDeque intDeque back <- popBackDeque intDeque logInfo $ "Front: " <> displayShow front -- Just 2 logInfo $ "Back: " <> displayShow back -- Just 4 -- Convert to list (non-destructive) items <- dequeToList intDeque logInfo $ "Items: " <> displayShow items -- [1, 3] -- Freeze to immutable vector vec <- freezeDeque @U.Vector intDeque logInfo $ "Vector: " <> displayShow vec -- [1, 3] -- Fold over deque total <- foldlDeque (acc x -> return (acc + x)) 0 intDeque logInfo $ "Sum: " <> display total -- 4 -- Boxed deque for complex types strDeque <- newDeque @B.MVector @Text pushBackDeque strDeque "hello" pushBackDeque strDeque "world" strings <- dequeToList strDeque logInfo $ "Strings: " <> displayShow strings -- ["hello", "world"] ``` -------------------------------- ### Atomic and Durable File Operations in Haskell Source: https://context7.com/commercialhaskell/rio/llms.txt Utilizes the RIO.File module for enhanced file operations, providing stronger durability and atomicity guarantees than standard library functions. Examples include atomic writes, durable writes, and combined durable-atomic writes to prevent data loss and partial writes. ```haskell {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-) import RIO import RIO.File import qualified RIO.ByteString as B main :: IO () main = runSimpleApp $ do let content = "Important data that must be saved safely\n" -- Standard binary file write writeBinaryFile "normal.txt" content -- Atomic write: writes to temp file, then renames -- Prevents partial writes on crash writeBinaryFileAtomic "atomic.txt" content -- Durable write: ensures data is fsynced to disk -- Survives system crash/power loss writeBinaryFileDurable "durable.txt" content -- Durable AND atomic: safest option -- Both prevents partial writes and ensures durability writeBinaryFileDurableAtomic "safe.txt" content -- Using withBinaryFile variants for handle-based operations withBinaryFileDurableAtomic "data.bin" WriteMode $ \handle -> do liftIO $ B.hPut handle "header\n" liftIO $ B.hPut handle "data\n" liftIO $ B.hPut handle "footer\n" -- Ensure existing file is durable (fsync) ensureFileDurable "safe.txt" -- Read file back result <- readFileBinary "safe.txt" logInfo $ "Read: " <> displayBytesUtf8 result ``` -------------------------------- ### Configure Process Contexts with RIO Source: https://context7.com/commercialhaskell/rio/llms.txt Demonstrates creating and configuring process contexts using RIO. This includes creating default contexts from the system environment, custom contexts with specific environment variables, modifying existing contexts, and augmenting the PATH environment variable. It also shows how to use `LoggedProcessContext` and `withProcessContextNoLogging` for integrated logging and process execution. ```haskell {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} import RIO import RIO.Process import qualified RIO.Map as Map main :: IO () main = do -- Create default process context from system environment defaultPc <- mkDefaultProcessContext -- Create custom process context with specific environment let customEnv = Map.fromList [ ("PATH", "/usr/local/bin:/usr/bin:/bin") , ("HOME", "/home/myuser") , ("LANG", "en_US.UTF-8") ] customPc <- mkProcessContext customEnv -- Modify existing process context modifiedPc <- modifyEnvVars defaultPc $ \env -> insertMap "MY_APP_DEBUG" "1" $ insertMap "MY_APP_LOG_LEVEL" "debug" env -- Use LoggedProcessContext for combined logging + process withProcessContextNoLogging $ do proc "env" [] runProcess_ -- Augment PATH with additional directories case augmentPathMap ["/opt/myapp/bin", "/custom/bin"] customEnv of Left err -> print err Right newEnv -> do pc <- mkProcessContext newEnv runRIO pc $ do path <- view exeSearchPathL liftIO $ putStrLn $ "Search path: " ++ show path -- Custom application environment with process context data MyApp = MyApp { maLogFunc :: !LogFunc , maProcessContext :: !ProcessContext } instance HasLogFunc MyApp where logFuncL = lens maLogFunc (\x y -> x { maLogFunc = y }) instance HasProcessContext MyApp where processContextL = lens maProcessContext (\x y -> x { maProcessContext = y }) runMyApp :: RIO MyApp a -> IO a runMyApp action = do pc <- mkDefaultProcessContext logOptions <- logOptionsHandle stderr True withLogFunc logOptions $ \lf -> do let app = MyApp lf pc runRIO app action ``` -------------------------------- ### Running Simple RIO Applications in Haskell Source: https://context7.com/commercialhaskell/rio/llms.txt Demonstrates the `runSimpleApp` function for quickly executing RIO actions with a default environment, including logging to stderr and process context. This is useful for scripts and straightforward applications. It shows basic logging and accessing environment variables like PATH. ```haskell #{-# LANGUAGE NoImplicitPrelude #-} #{-# LANGUAGE OverloadedStrings #-} import RIO main :: IO () main = runSimpleApp $ do logInfo "Starting simple application..." logDebug "This is a debug message" logWarn "This is a warning" logError "This is an error message" -- Access process context mPath <- lookupEnvFromContext "PATH" case mPath of Nothing -> logWarn "PATH not found" Just path -> logDebug $ "PATH is set: " <> display (take 50 path) <> "..." logInfo "Application finished" -- To enable verbose logging, set RIO_VERBOSE=1 environment variable -- $ RIO_VERBOSE=1 ./my-app ``` -------------------------------- ### Configuring and Using the Logging System in Haskell Source: https://context7.com/commercialhaskell/rio/llms.txt Illustrates how to configure and use the RIO logging system in Haskell. It covers setting up log options (stderr, verbose, time, location, color, minimum level) and demonstrates various logging functions including standard levels, custom levels, source annotations, and sticky logging for progress indicators. Requires `RIO` library. ```haskell #{-# LANGUAGE NoImplicitPrelude #-} #{-# LANGUAGE OverloadedStrings #-} import RIO main :: IO () main = do -- Create log options for stderr with verbose mode logOptions <- logOptionsHandle stderr True -- Customize log options let logOptions' = setLogUseTime True $ setLogUseLoc True $ setLogUseColor True $ setLogMinLevel LevelDebug $ logOptions withLogFunc logOptions' $ \lf -> runRIO lf $ do -- Standard logging functions logDebug "Debug: detailed information for debugging" logInfo "Info: general information about program execution" logWarn "Warning: something unexpected but not critical" logError "Error: something went wrong" -- Log with custom level logOther "AUDIT" "Custom log level for auditing" -- Log with source annotation logInfoS "database" "Connected to PostgreSQL" logDebugS "http" "Request received: GET /api/users" -- Sticky logging for progress (stays at bottom of terminal) logSticky "Processing: 0%" -- ... do work ... logSticky "Processing: 50%" -- ... do more work ... logStickyDone "Processing: 100% - Complete!" -- Output (verbose mode): -- 2024-01-15 10:30:45.123456: [debug] Debug: detailed information... -- @(Main.hs:20:5) -- 2024-01-15 10:30:45.123789: [info] Info: general information... -- @(Main.hs:21:5) ``` -------------------------------- ### RIO Monad for I/O Operations Source: https://github.com/commercialhaskell/rio/blob/master/rio/README.md Demonstrates the recommended way to define functions that perform I/O using the RIO monad, emphasizing typeclass constraints for environment access over concrete types for better composability. ```haskell class HasConfig env where configL :: Lens' env Config -- more on this in a moment myFunction :: HasConfig env => RIO env Foo ``` -------------------------------- ### Configure and Create Logging Functions with RIO Source: https://context7.com/commercialhaskell/rio/llms.txt Demonstrates how to configure and create custom logging functions using RIO's `withLogFunc` and `LogOptions`. It covers setting log levels, colors, timestamps, verbosity, and output formats. This function requires the `RIO` library. ```haskell {-# LANGUAGE NoImplicitPrelude #} {-# LANGUAGE OverloadedStrings #} import RIO -- Custom log colors customLogColors :: LogLevel -> Utf8Builder customLogColors LevelDebug = "\ESC[36m" -- Cyan customLogColors LevelInfo = "\ESC[32m" -- Green customLogColors LevelWarn = "\ESC[33m" -- Yellow customLogColors LevelError = "\ESC[91m" -- Bright Red customLogColors _ = "\ESC[35m" -- Magenta main :: IO () main = do -- Create basic log options baseOptions <- logOptionsHandle stderr False -- non-verbose by default -- Fully customize the log options let options = setLogMinLevel LevelDebug $ setLogVerboseFormat True $ setLogUseTime True $ setLogUseLoc False $ setLogUseColor True $ setLogLevelColors customLogColors $ setLogSecondaryColor "\ESC[90m" -- Gray for timestamps $ setLogFormat (\msg -> "[MyApp] " <> msg) $ baseOptions withLogFunc options $ \logFunc -> do -- logFunc can be combined (logs to both) let combinedLogFunc = logFunc <> logFunc runRIO logFunc $ do logInfo "Application started with custom logging" logDebug "Custom colors are now active" -- For testing, capture logs in memory testLogging :: IO Text testLogging = do (ref, options) <- logOptionsMemory withLogFunc options $ \lf -> runRIO lf $ do logInfo "Test message" builder <- readIORef ref return $ utf8BuilderToText $ Utf8Builder builder ``` -------------------------------- ### RIO Monad Environment with Typeclasses and Lenses (Haskell) Source: https://github.com/commercialhaskell/rio/blob/master/README.md Demonstrates how to define and compose environments for the RIO monad using typeclasses and lenses. This approach enhances composability by allowing functions to depend on typeclass constraints rather than concrete environment types. ```haskell class HasLogFunc env where logFuncL :: Lens' env LogFunc class HasConfig env where configL :: Lens' env Config instance HasConfig Config where configL = id data Env = Env { envLogFunc :: !LogFunc, envConfig :: !Config } class (HasLogFunc env, HasConfig env) => HasEnv env where envL :: Lens' env Env instance HasLogFunc Env where logFuncL = lens envLogFunc (\x y -> x { envLogFunc = y }) instance HasConfig Env where configL = lens envConfig (\x y -> x { envConfig = y }) instance HasEnv Env where envL = id -- And then, at some other part of the code data SuperEnv = SuperEnv { seEnv :: !Env, seOtherStuff :: !OtherStuff } instance HasLogFunc SuperEnv where logFuncL = envL.logFuncL instance HasConfig SuperEnv where configL = envL.configL instance HasEnv SuperEnv where envL = lens seEnv (\x y -> x { seEnv = y }) ``` -------------------------------- ### Execute Processes with Enhanced Features using RIO.Process Source: https://context7.com/commercialhaskell/rio/llms.txt Details the `RIO.Process` module for enhanced process execution, including PATH caching, environment variable management, working directory control, and automatic debug logging. It demonstrates capturing output, modifying environment variables, changing directories, checking executable existence, finding executables, and handling long-running processes with streaming. ```haskell {-# LANGUAGE NoImplicitPrelude #} {-# LANGUAGE OverloadedStrings #} import RIO import RIO.Process main :: IO () main = runSimpleApp $ do -- Simple process execution proc "echo" ["Hello", "World"] runProcess_ -- Capture stdout (exitCode, stdout, stderr) <- proc "ls" ["-la"] readProcess logInfo $ "Exit code: " <> displayShow exitCode logInfo $ "Output: " <> displayBytesUtf8 (toStrictBytes stdout) -- Run with modified environment withModifyEnvVars (insertMap "MY_VAR" "my_value") $ do proc "printenv" ["MY_VAR"] runProcess_ -- Run in a specific working directory withWorkingDir "/tmp" $ do proc "pwd" [] runProcess_ -- Check if executable exists gitExists <- doesExecutableExist "git" when gitExists $ do proc "git" ["--version"] runProcess_ -- Find executable path ePath <- findExecutable "python3" case ePath of Left err -> logError $ "Python not found: " <> displayShow err Right path -> logInfo $ "Python at: " <> fromString path -- Long-running process with streaming proc "tail" ["-f", "/var/log/syslog"] $ \config -> do withProcessWait (setStdout createPipe config) $ \process -> do -- Read from stdout handle let stdoutHandle = getStdout process line <- liftIO $ hGetLine stdoutHandle logInfo $ "First line: " <> displayBytesUtf8 line stopProcess process ``` -------------------------------- ### Handle Exceptions with RIO Source: https://context7.com/commercialhaskell/rio/llms.txt Illustrates exception handling in RIO, which re-exports functionalities from unliftio. It covers defining custom exceptions, throwing and catching specific exceptions using `try`, catching all synchronous exceptions with `tryAny`, managing resources with `bracket`, ensuring cleanup with `finally`, and performing error-specific cleanup with `onException`. ```haskell {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveAnyClass #-} import RIO -- Define application-specific exceptions data AppException = ConfigError Text | DatabaseError Text | NetworkError Text deriving (Show, Typeable) instance Exception AppException main :: IO () main = runSimpleApp $ do -- Throw and catch exceptions result <- try @_ @AppException $ do throwIO $ ConfigError "Missing database URL" case result of Left (ConfigError msg) -> logError $ "Config error: " <> display msg Left err -> logError $ "Other error: " <> displayShow err Right _ -> logInfo "Success" -- Use tryAny for catching all synchronous exceptions outcome <- tryAny $ do -- Risky operation error "Something went wrong" case outcome of Left e -> logWarn $ "Caught exception: " <> display e Right _ -> logInfo "Operation succeeded" -- Resource management with bracket bracket (do logInfo "Acquiring resource"; return ("resource" :: Text)) (\r -> logInfo $ "Releasing: " <> display r) (\r -> logInfo $ "Using: " <> display r) -- finally for cleanup (logInfo "Main action") `finally` (logInfo "Cleanup action") -- onException for error-specific cleanup (throwIO $ NetworkError "Connection failed") `onException` (logError "Cleaning up after network error") `catch` (\(NetworkError msg) -> logWarn $ "Handled: " <> display msg) ``` -------------------------------- ### Defining Has-Style Typeclasses with Lenses in RIO Source: https://github.com/commercialhaskell/rio/blob/master/rio/README.md Illustrates how to define Has-style typeclasses for environments using lenses and superclasses in Haskell, showing practical composition with concrete and nested environments. ```haskell -- Defined in RIO.Logger class HasLogFunc env where logFuncL :: Lens' env LogFunc class HasConfig env where configL :: Lens' env Config instance HasConfig Config where configL = id data Env = Env { envLogFunc :: !LogFunc, envConfig :: !Config } class (HasLogFunc env, HasConfig env) => HasEnv env where envL :: Lens' env Env instance HasLogFunc Env where logFuncL = lens envLogFunc (\x y -> x { envLogFunc = y }) instance HasConfig Env where configL = lens envConfig (\x y -> x { envConfig = y }) instance HasEnv Env where envL = id -- And then, at some other part of the code data SuperEnv = SuperEnv { seEnv :: !Env, seOtherStuff :: !OtherStuff } instance HasLogFunc SuperEnv where logFuncL = envL.logFuncL instance HasConfig SuperEnv where configL = envL.configL instance HasEnv SuperEnv where envL = lens seEnv (\x y -> x { seEnv = y }) ``` -------------------------------- ### Recommended Haskell Language Extensions Source: https://github.com/commercialhaskell/rio/blob/master/rio/README.md A list of Haskell language extensions recommended for general use in the Rio project. These extensions are widely accepted, cause minimal code breakage, and are considered safe. They should typically be enabled on a per-module basis. ```text AutoDeriveTypeable BangPatterns BinaryLiterals ConstraintKinds DataKinds DefaultSignatures DeriveDataTypeable DeriveFoldable DeriveFunctor DeriveGeneric DeriveTraversable DoAndIfThenElse EmptyDataDecls ExistentialQuantification FlexibleContexts FlexibleInstances FunctionalDependencies GADTs GeneralizedNewtypeDeriving InstanceSigs KindSignatures LambdaCase MonadFailDesugaring MultiParamTypeClasses MultiWayIf NamedFieldPuns NoImplicitPrelude OverloadedStrings PartialTypeSignatures PatternGuards PolyKinds RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving TupleSections TypeFamilies TypeSynonymInstances ViewPatterns ``` -------------------------------- ### Recommended GHC Warning Flags Source: https://github.com/commercialhaskell/rio/blob/master/rio/README.md A set of GHC compiler warning flags recommended for all projects to help identify potential issues. These flags encourage more robust code by warning about incomplete patterns, redundant constraints, and other common pitfalls. ```text -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints ``` -------------------------------- ### Implement Human-Friendly Text Representation with Display Typeclass Source: https://context7.com/commercialhaskell/rio/llms.txt Illustrates the use of the `Display` typeclass in RIO for creating human-friendly text representations of data types, which is more efficient for UTF-8 output than the standard `Show` typeclass. It shows how to implement `Display` for custom data types and use it within logging functions. ```haskell {-# LANGUAGE NoImplicitPrelude #} {-# LANGUAGE OverloadedStrings #} import RIO -- Define a custom data type data User = User { userName :: !Text , userAge :: !Int , userRole :: !Text } -- Implement Display for human-readable output instance Display User where display user = "User(" <> display (userName user) <> ", age=" <> display (userAge user) <> ", role=" <> display (userRole user) <> ")" -- Alternative: use textDisplay for Text-based display data Request = Request { reqMethod :: !Text , reqPath :: !Text } instance Display Request where textDisplay req = reqMethod req <> " " <> reqPath req main :: IO () main = runSimpleApp $ do let user = User "Alice" 30 "admin" req = Request "GET" "/api/users" -- Display works directly in log messages logInfo $ "Processing: " <> display user logInfo $ "Incoming: " <> display req -- Convert Utf8Builder to Text let userText = utf8BuilderToText $ display user logDebug $ "As text: " <> display userText -- Use displayShow for Show instances let numbers = [1, 2, 3] :: [Int] logInfo $ "Numbers: " <> displayShow numbers -- Write directly to file writeFileUtf8Builder "output.txt" $ display user <> "\n" <> display req <> "\n" ``` -------------------------------- ### Haskell Type-Safe Logging with GLogFunc Source: https://context7.com/commercialhaskell/rio/llms.txt This Haskell code defines typed log messages for different application components and implements the necessary typeclass instances for RIO's GLogFunc. It demonstrates how to create a generic logger that supports semantic logging, allowing for structured log data. ```haskell #!/usr/bin/env runhaskell {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-} import RIO -- Define typed log messages for different components data DatabaseMsg = DbConnected Text | DbQuery Text | DbDisconnected deriving Show data HttpMsg = HttpRequest Text Text -- method, path | HttpResponse Int -- status code | HttpError Text deriving Show data AppMsg = AppInit Text | AppDatabase DatabaseMsg | AppHttp HttpMsg | AppShutdown deriving Show -- Implement HasLogLevel for integration with classic logger instance HasLogLevel AppMsg where getLogLevel (AppInit _) = LevelInfo getLogLevel (AppDatabase (DbQuery _)) = LevelDebug getLogLevel (AppDatabase _) = LevelInfo getLogLevel (AppHttp (HttpError _)) = LevelError getLogLevel (AppHttp _) = LevelInfo getLogLevel AppShutdown = LevelInfo instance HasLogSource AppMsg where getLogSource (AppDatabase _) = "database" getLogSource (AppHttp _) = "http" getLogSource _ = "app" instance Display AppMsg where display (AppInit msg) = "Initializing: " <> display msg display (AppDatabase (DbConnected host)) = "Connected to " <> display host display (AppDatabase (DbQuery sql)) = "Query: " <> display sql display (AppDatabase DbDisconnected) = "Disconnected from database" display (AppHttp (HttpRequest m p)) = display m <> " " <> display p display (AppHttp (HttpResponse code)) = "Response: " <> display code display (AppHttp (HttpError e)) = "HTTP Error: " <> display e display AppShutdown = "Shutting down" -- Database layer uses DatabaseMsg runDatabase :: RIO (GLogFunc DatabaseMsg) () runDatabase = do glog $ DbConnected "localhost:5432" glog $ DbQuery "SELECT * FROM users" glog DbDisconnected -- HTTP layer uses HttpMsg runHttp :: RIO (GLogFunc HttpMsg) () runHttp = do glog $ HttpRequest "GET" "/api/users" glog $ HttpResponse 200 main :: IO () main = do logOptions <- logOptionsHandle stderr True withLogFunc logOptions $ \lf -> do -- Create GLogFunc that integrates with classic logger let appGLog = gLogFuncClassic lf :: GLogFunc AppMsg runRIO appGLog $ do glog $ AppInit "Starting application" -- Transform logger for database layer mapRIO (contramapGLogFunc AppDatabase) runDatabase -- Transform logger for HTTP layer mapRIO (contramapGLogFunc AppHttp) runHttp glog AppShutdown ``` -------------------------------- ### Mutable References with MonadState/MonadWriter in Haskell Source: https://context7.com/commercialhaskell/rio/llms.txt Demonstrates the use of `SomeRef` to provide a uniform interface for mutable references within the RIO monad. This allows for seamless integration with `MonadState` and `MonadWriter` without requiring transformer stacks, simplifying state and effect management. ```haskell {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-) {-# LANGUAGE FlexibleContexts #-) import RIO import Control.Monad.State (MonadState, get, put, modify) import Control.Monad.Writer (MonadWriter, tell) -- Environment with state and writer refs data AppEnv = AppEnv { envLogFunc :: !LogFunc , envStateRef :: !(SomeRef Int) , envWriterRef :: !(SomeRef [Text]) } instance HasLogFunc AppEnv where logFuncL = lens envLogFunc (\x y -> x { envLogFunc = y }) instance HasStateRef Int AppEnv where stateRefL = lens envStateRef (\x y -> x { envStateRef = y }) instance HasWriteRef [Text] AppEnv where writeRefL = lens envWriterRef (\x y -> x { envWriterRef = y }) -- Now you can use MonadState and MonadWriter! appLogic :: (HasLogFunc env, HasStateRef Int env, HasWriteRef [Text] env) => RIO env () appLogic = do -- Use MonadState operations counter <- get logInfo $ "Current counter: " <> display counter put (counter + 1) modify (+10) newCounter <- get logInfo $ "New counter: " <> display newCounter -- Use MonadWriter operations tell ["Started processing"] tell ["Step 1 complete"] tell ["Step 2 complete"] logInfo "Logic complete" main :: IO () main = do logOptions <- logOptionsHandle stderr False withLogFunc logOptions $ \lf -> do -- Create boxed SomeRef for complex types stateRef <- newSomeRef (0 :: Int) writerRef <- newSomeRef ([] :: [Text]) let env = AppEnv lf stateRef writerRef runRIO env appLogic -- Read final values finalState <- readSomeRef stateRef logs <- readSomeRef writerRef putStrLn $ "Final state: " ++ show finalState putStrLn $ "Logs: " ++ show logs ``` -------------------------------- ### Optional Haskell Language Extensions Source: https://github.com/commercialhaskell/rio/blob/master/rio/README.md A list of Haskell language extensions that are acceptable but not recommended for default enablement in the Rio project due to potential tooling conflicts or other considerations. These include extensions like CPP, TemplateHaskell, and QuasiQuotes. ```text CPP TemplateHaskell ForeignFunctionInterface MagicHash UnliftedFFITypes TypeOperators UnboxedTuples PackageImports QuasiQuotes DeriveAnyClass DeriveLift StaticPointers ``` -------------------------------- ### Custom Application Exception Type in Haskell Source: https://github.com/commercialhaskell/rio/blob/master/rio/README.md Defines a custom algebraic data type for application-specific exceptions in Haskell, implementing the Exception and Show typeclasses for proper handling and display. ```haskell data AppExceptions = NetworkChangeError Text | FilePathError FilePath | ImpossibleError deriving (Typeable) instance Exception AppExceptions instance Show AppExceptions where show = \case NetworkChangeError err -> "network error: " <> (unpack err) FilePathError fp -> "error accessing filepath at: " <> fp ImpossibleError -> "this codepath should never have been executed. Please report a bug." ``` -------------------------------- ### RIO Monad Definition and Usage in Haskell Source: https://context7.com/commercialhaskell/rio/llms.txt Defines and demonstrates the RIO monad, a Reader+IO monad for passing environment through Haskell applications. It includes custom environment types, typeclass instances for environment access, and application logic using the RIO monad. Requires `RIO` and `lens` libraries. ```haskell #{-# LANGUAGE NoImplicitPrelude #-} #{-# LANGUAGE OverloadedStrings #-} import RIO -- Define your application environment data App = App { appLogFunc :: !LogFunc , appConfig :: !Config } data Config = Config { configDbHost :: !Text , configPort :: !Int } -- Implement HasLogFunc for your environment instance HasLogFunc App where logFuncL = lens appLogFunc (\x y -> x { appLogFunc = y }) -- Define a HasConfig typeclass for flexible access class HasConfig env where configL :: Lens' env Config instance HasConfig App where configL = lens appConfig (\x y -> x { appConfig = y }) -- Application logic using RIO monad myApp :: (HasLogFunc env, HasConfig env) => RIO env () myApp = do cfg <- view configL logInfo $ "Connecting to database at: " <> display (configDbHost cfg) logDebug $ "Port: " <> display (configPort cfg) -- Your application logic here -- Run the application main :: IO () main = do logOptions <- logOptionsHandle stderr True -- verbose mode withLogFunc logOptions $ \lf -> do let app = App { appLogFunc = lf , appConfig = Config "localhost" 5432 } runRIO app myApp ``` -------------------------------- ### Production GHC Error Flag Source: https://github.com/commercialhaskell/rio/blob/master/rio/README.md A GHC compiler flag recommended for production builds. This flag turns all warnings into errors, forcing developers to resolve potential issues before shipping code. ```text -Werror ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.