├── .github └── workflows │ └── tests.yml ├── .gitignore ├── LICENSE ├── README.md ├── etc ├── .gitignore ├── make-template.hs ├── stack.yaml ├── stack.yaml.lock └── template │ ├── .gitignore │ ├── ChangeLog.md │ ├── LICENSE │ ├── README.md │ ├── Setup.hs │ ├── app │ └── Main.hs │ ├── package.yaml │ ├── src │ ├── Import.hs │ ├── Run.hs │ ├── Types.hs │ └── Util.hs │ └── test │ ├── Spec.hs │ └── UtilSpec.hs ├── rio-orphans ├── ChangeLog.md ├── LICENSE ├── README.md ├── Setup.hs ├── package.yaml ├── src │ └── RIO │ │ └── Orphans.hs └── test │ ├── RIO │ └── OrphansSpec.hs │ └── Spec.hs ├── rio ├── ChangeLog.md ├── LICENSE ├── README.md ├── package.yaml ├── src │ ├── RIO.hs │ └── RIO │ │ ├── ByteString.hs │ │ ├── ByteString │ │ ├── Lazy.hs │ │ ├── Lazy │ │ │ └── Partial.hs │ │ └── Partial.hs │ │ ├── Char.hs │ │ ├── Char │ │ └── Partial.hs │ │ ├── Deque.hs │ │ ├── Directory.hs │ │ ├── File.hs │ │ ├── FilePath.hs │ │ ├── HashMap.hs │ │ ├── HashMap │ │ └── Partial.hs │ │ ├── HashSet.hs │ │ ├── Lens.hs │ │ ├── List.hs │ │ ├── List │ │ └── Partial.hs │ │ ├── Map.hs │ │ ├── Map │ │ ├── Partial.hs │ │ └── Unchecked.hs │ │ ├── NonEmpty.hs │ │ ├── NonEmpty │ │ └── Partial.hs │ │ ├── Partial.hs │ │ ├── Prelude.hs │ │ ├── Prelude │ │ ├── Display.hs │ │ ├── Exit.hs │ │ ├── Extra.hs │ │ ├── IO.hs │ │ ├── Lens.hs │ │ ├── Logger.hs │ │ ├── RIO.hs │ │ ├── Reexports.hs │ │ ├── Renames.hs │ │ ├── Simple.hs │ │ ├── Text.hs │ │ ├── Trace.hs │ │ ├── Types.hs │ │ └── URef.hs │ │ ├── Process.hs │ │ ├── Seq.hs │ │ ├── Set.hs │ │ ├── Set │ │ ├── Partial.hs │ │ └── Unchecked.hs │ │ ├── State.hs │ │ ├── Text.hs │ │ ├── Text │ │ ├── Lazy.hs │ │ ├── Lazy │ │ │ └── Partial.hs │ │ └── Partial.hs │ │ ├── Time.hs │ │ ├── Vector.hs │ │ ├── Vector │ │ ├── Boxed.hs │ │ ├── Boxed │ │ │ ├── Partial.hs │ │ │ └── Unsafe.hs │ │ ├── Partial.hs │ │ ├── Storable.hs │ │ ├── Storable │ │ │ ├── Partial.hs │ │ │ └── Unsafe.hs │ │ ├── Unboxed.hs │ │ ├── Unboxed │ │ │ ├── Partial.hs │ │ │ └── Unsafe.hs │ │ └── Unsafe.hs │ │ └── Writer.hs └── test │ ├── RIO │ ├── DequeSpec.hs │ ├── FileSpec.hs │ ├── ListSpec.hs │ ├── LoggerSpec.hs │ ├── Prelude │ │ ├── ExtraSpec.hs │ │ ├── IOSpec.hs │ │ ├── RIOSpec.hs │ │ └── SimpleSpec.hs │ ├── PreludeSpec.hs │ └── TextSpec.hs │ └── Spec.hs ├── stack.yaml └── stack.yaml.lock /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | build: 11 | name: CI 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | os: [ubuntu-latest, macos-latest, windows-latest] 17 | resolver: 18 | - nightly 19 | - lts-18 20 | - lts-16 21 | - lts-14 22 | 23 | steps: 24 | - name: Clone project 25 | uses: actions/checkout@v2 26 | 27 | - name: Build and run tests 28 | shell: bash 29 | run: | 30 | set -ex 31 | mkdir -p ../_newstack 32 | stack upgrade --force-download --local-bin-path ../_newstack 33 | ../_newstack/stack --version 34 | ../_newstack/stack test --fast --no-terminal --resolver=${{ matrix.resolver }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | tarballs/ 3 | .stack-work/ 4 | *.cabal 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | rio/LICENSE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rio/README.md -------------------------------------------------------------------------------- /etc/.gitignore: -------------------------------------------------------------------------------- 1 | /rio.hsfiles 2 | template/PROJECTNAME.cabal 3 | -------------------------------------------------------------------------------- /etc/make-template.hs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env stack 2 | -- stack --resolver lts-14.10 script 3 | {-# LANGUAGE NoImplicitPrelude #-} 4 | {-# LANGUAGE OverloadedStrings #-} 5 | {-# LANGUAGE RecordWildCards #-} 6 | import Conduit 7 | import RIO 8 | import qualified RIO.ByteString as B 9 | import qualified RIO.ByteString.Lazy as BL 10 | import RIO.FilePath 11 | import RIO.Process 12 | import qualified RIO.Text as T 13 | import qualified RIO.Text.Partial as T (replace) 14 | import RIO.Time 15 | import Text.ProjectTemplate 16 | 17 | data App = App 18 | { appLogFunc :: !LogFunc 19 | , appProcessContext :: !ProcessContext 20 | } 21 | 22 | instance HasLogFunc App where 23 | logFuncL = lens appLogFunc (\x y -> x { appLogFunc = y }) 24 | instance HasProcessContext App where 25 | processContextL = lens appProcessContext (\x y -> x { appProcessContext = y }) 26 | 27 | start :: RIO App a -> IO a 28 | start inner = do 29 | appProcessContext <- mkDefaultProcessContext 30 | lo <- logOptionsHandle stderr True 31 | withLogFunc lo $ \appLogFunc -> runRIO App {..} inner 32 | 33 | splitNulls :: ByteString -> [ByteString] 34 | splitNulls bs 35 | | B.null bs = [] 36 | | otherwise = 37 | let (x, y) = B.break (== 0) bs 38 | in x : splitNulls (B.drop 1 y) 39 | 40 | decode :: ByteString -> RIO App FilePath 41 | decode bs = 42 | case decodeUtf8' bs of 43 | Left e -> throwIO e 44 | Right x -> return $ T.unpack x 45 | 46 | readReplace :: MonadIO m => FilePath -> m ByteString 47 | readReplace fp = do 48 | (year, _, _) <- toGregorian . utctDay <$> getCurrentTime 49 | (encodeUtf8 . replaces year) <$> readFileUtf8 fp 50 | where 51 | replaces year 52 | = T.replace "PROJECTNAME" "{{name}}" 53 | . T.replace "Paths_PROJECTNAME" "Paths_{{name-as-varid}}" 54 | . T.replace "AUTHOR" "{{author-name}}{{^author-name}}Author name here{{/author-name}}" 55 | . T.replace "MAINTAINER" "{{author-email}}{{^author-email}}example@example.com{{/author-email}}" 56 | . T.replace "GITHUB" "{{github-username}}{{^github-username}}githubuser{{/github-username}}/{{name}}" 57 | . T.replace "DESCRIPTION" "Please see the README on Github at " 58 | . T.replace "COPYRIGHT" 59 | (T.concat 60 | [ "{{copyright}}{{^copyright}}{{year}}{{^year}}" 61 | , T.pack $ show year 62 | , "{{/year}} {{author-name}}{{^author-name}}Author name here{{/author-name}}{{/copyright}}" 63 | ]) 64 | 65 | main :: IO () 66 | main = start $ do 67 | let templatedir = "template" 68 | 69 | -- Make sure it passes 70 | proc "stack" ["test"] runProcess_ 71 | 72 | rawout <- withWorkingDir templatedir 73 | $ proc "git" ["ls-files", "-z"] 74 | readProcessStdout_ 75 | files <- mapM decode $ splitNulls $ BL.toStrict rawout 76 | let src = forM_ files $ \fp -> yield (fp, readReplace $ templatedir fp) 77 | runConduitRes $ src .| createTemplate .| sinkFile "rio.hsfiles" 78 | -------------------------------------------------------------------------------- /etc/stack.yaml: -------------------------------------------------------------------------------- 1 | resolver: lts-14.10 2 | packages: 3 | - template 4 | extra-deps: 5 | - ../rio 6 | -------------------------------------------------------------------------------- /etc/stack.yaml.lock: -------------------------------------------------------------------------------- 1 | # This file was autogenerated by Stack. 2 | # You should not edit this file by hand. 3 | # For more information, please see the documentation at: 4 | # https://docs.haskellstack.org/en/stable/lock_files 5 | 6 | packages: [] 7 | snapshots: 8 | - completed: 9 | size: 524130 10 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/10.yaml 11 | sha256: 04841e0397d7ce6364f19359fce89aa45ca8684609d665845db80d398002baa9 12 | original: lts-14.10 13 | -------------------------------------------------------------------------------- /etc/template/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swp 3 | tarballs/ 4 | .stack-work/ 5 | -------------------------------------------------------------------------------- /etc/template/ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Changelog for PROJECTNAME 2 | 3 | ## Unreleased changes 4 | -------------------------------------------------------------------------------- /etc/template/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright AUTHOR (c) 2019 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Author name here nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /etc/template/README.md: -------------------------------------------------------------------------------- 1 | # PROJECTNAME 2 | 3 | ## Execute 4 | 5 | * Run `stack exec -- {{name}}-exe` to see "We're inside the application!" 6 | * With `stack exec -- {{name}}-exe --verbose` you will see the same message, with more logging. 7 | 8 | ## Run tests 9 | 10 | `stack test` 11 | -------------------------------------------------------------------------------- /etc/template/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /etc/template/app/Main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | {-# LANGUAGE TemplateHaskell #-} 3 | module Main (main) where 4 | 5 | import Import 6 | import Run 7 | import RIO.Process 8 | import Options.Applicative.Simple 9 | import qualified Paths_PROJECTNAME 10 | 11 | main :: IO () 12 | main = do 13 | (options, ()) <- simpleOptions 14 | $(simpleVersion Paths_PROJECTNAME.version) 15 | "Header for command line arguments" 16 | "Program description, also for command line arguments" 17 | (Options 18 | <$> switch ( long "verbose" 19 | <> short 'v' 20 | <> help "Verbose output?" 21 | ) 22 | ) 23 | empty 24 | lo <- logOptionsHandle stderr (optionsVerbose options) 25 | pc <- mkDefaultProcessContext 26 | withLogFunc lo $ \lf -> 27 | let app = App 28 | { appLogFunc = lf 29 | , appProcessContext = pc 30 | , appOptions = options 31 | } 32 | in runRIO app run 33 | -------------------------------------------------------------------------------- /etc/template/package.yaml: -------------------------------------------------------------------------------- 1 | name: PROJECTNAME 2 | version: 0.1.0.0 3 | github: GITHUB 4 | license: BSD3 5 | author: AUTHOR 6 | maintainer: MAINTAINER 7 | copyright: COPYRIGHT 8 | 9 | extra-source-files: 10 | - README.md 11 | - ChangeLog.md 12 | 13 | # Metadata used when publishing your package 14 | # synopsis: Short description of your package 15 | # category: Web 16 | 17 | # To avoid duplicated efforts in documentation and dealing with the 18 | # complications of embedding Haddock markup inside cabal files, it is 19 | # common to point users to the README.md file. 20 | description: DESCRIPTION 21 | 22 | dependencies: 23 | - base >= 4.11 && < 10 24 | - rio >= 0.1.12.0 25 | 26 | ghc-options: 27 | - -Wall 28 | - -Wcompat 29 | - -Widentities 30 | - -Wincomplete-record-updates 31 | - -Wincomplete-uni-patterns 32 | - -Wpartial-fields 33 | - -Wredundant-constraints 34 | 35 | library: 36 | source-dirs: src 37 | 38 | executables: 39 | PROJECTNAME-exe: 40 | main: Main.hs 41 | source-dirs: app 42 | dependencies: 43 | - PROJECTNAME 44 | - optparse-simple 45 | 46 | ghc-options: 47 | - -threaded 48 | - -rtsopts 49 | - -with-rtsopts=-N 50 | 51 | tests: 52 | PROJECTNAME-test: 53 | main: Spec.hs 54 | source-dirs: test 55 | dependencies: 56 | - PROJECTNAME 57 | - hspec 58 | 59 | ghc-options: 60 | - -threaded 61 | - -rtsopts 62 | - -with-rtsopts=-N 63 | -------------------------------------------------------------------------------- /etc/template/src/Import.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | module Import 3 | ( module RIO 4 | , module Types 5 | ) where 6 | 7 | import RIO 8 | import Types 9 | -------------------------------------------------------------------------------- /etc/template/src/Run.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | module Run (run) where 4 | 5 | import Import 6 | 7 | run :: RIO App () 8 | run = do 9 | logInfo "We're inside the application!" 10 | -------------------------------------------------------------------------------- /etc/template/src/Types.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | module Types where 3 | 4 | import RIO 5 | import RIO.Process 6 | 7 | -- | Command line arguments 8 | data Options = Options 9 | { optionsVerbose :: !Bool 10 | } 11 | 12 | data App = App 13 | { appLogFunc :: !LogFunc 14 | , appProcessContext :: !ProcessContext 15 | , appOptions :: !Options 16 | -- Add other app-specific configuration information here 17 | } 18 | 19 | instance HasLogFunc App where 20 | logFuncL = lens appLogFunc (\x y -> x { appLogFunc = y }) 21 | instance HasProcessContext App where 22 | processContextL = lens appProcessContext (\x y -> x { appProcessContext = y }) 23 | -------------------------------------------------------------------------------- /etc/template/src/Util.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | -- | Silly utility module, used to demonstrate how to write a test 3 | -- case. 4 | module Util 5 | ( plus2 6 | ) where 7 | 8 | import RIO 9 | 10 | plus2 :: Int -> Int 11 | plus2 = (+ 2) 12 | -------------------------------------------------------------------------------- /etc/template/test/Spec.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -F -pgmF hspec-discover #-} 2 | -------------------------------------------------------------------------------- /etc/template/test/UtilSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | module UtilSpec (spec) where 3 | 4 | import Import 5 | import Util 6 | import Test.Hspec 7 | import Test.Hspec.QuickCheck 8 | 9 | spec :: Spec 10 | spec = do 11 | describe "plus2" $ do 12 | it "basic check" $ plus2 0 `shouldBe` 2 13 | it "overflow" $ plus2 maxBound `shouldBe` minBound + 1 14 | prop "minus 2" $ \i -> plus2 i - 2 `shouldBe` i 15 | -------------------------------------------------------------------------------- /rio-orphans/ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Changelog for rio-orphans 2 | 3 | ## 0.1.2.0 4 | 5 | * Add an instance for `MonadLoggerIO` typeclass, from the `monad-logger` library 6 | 7 | ## 0.1.1.0 8 | 9 | * Add an instance for `MonadLogger` typeclass, from the `monad-logger` library 10 | 11 | ## 0.1.0.0 12 | 13 | * Initial release 14 | -------------------------------------------------------------------------------- /rio-orphans/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Michael Snoyman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /rio-orphans/README.md: -------------------------------------------------------------------------------- 1 | # rio-orphans 2 | 3 | Provides orphan instances for the `RIO` data type. Currently supports: 4 | 5 | * `MonadBase` from `transformers-base` 6 | * `MonadBaseControl` from `monad-control` 7 | * `MonadCatch` and `MonadMask` from `exceptions` 8 | * `MonadLogger` from `monad-logger` 9 | * `MonadResource` from `resourcet` 10 | -------------------------------------------------------------------------------- /rio-orphans/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /rio-orphans/package.yaml: -------------------------------------------------------------------------------- 1 | name: rio-orphans 2 | version: 0.1.2.0 3 | synopsis: Orphan instances for the RIO type in the rio package 4 | description: See README and Haddocks at 5 | license: MIT 6 | author: Michael Snoyman 7 | maintainer: michael@snoyman.com 8 | github: commercialhaskell/rio 9 | category: Control 10 | 11 | extra-source-files: 12 | - README.md 13 | - ChangeLog.md 14 | 15 | dependencies: 16 | - base >= 4.12 && < 10 17 | - exceptions 18 | - resourcet 19 | - rio 20 | - monad-control 21 | - monad-logger 22 | - fast-logger 23 | - transformers-base 24 | - unliftio-core 25 | 26 | library: 27 | source-dirs: src 28 | 29 | tests: 30 | rio-orphans-test: 31 | main: Spec.hs 32 | source-dirs: test 33 | ghc-options: 34 | - -threaded 35 | - -rtsopts 36 | - -with-rtsopts=-N 37 | dependencies: 38 | - rio-orphans 39 | - hspec 40 | -------------------------------------------------------------------------------- /rio-orphans/src/RIO/Orphans.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances #-} 2 | {-# LANGUAGE ImplicitParams #-} 3 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | {-# LANGUAGE NoImplicitPrelude #-} 6 | {-# LANGUAGE StandaloneDeriving #-} 7 | {-# LANGUAGE TypeFamilies #-} 8 | {-# OPTIONS_GHC -fno-warn-orphans #-} 9 | -- | Orphan instances for the 'RIO' data type. 10 | module RIO.Orphans 11 | ( HasResourceMap (..) 12 | , ResourceMap 13 | , withResourceMap 14 | ) where 15 | 16 | import RIO 17 | import Control.Monad.Catch (MonadCatch, MonadMask) 18 | import Control.Monad.Base (MonadBase) 19 | import Control.Monad.IO.Unlift (askRunInIO) 20 | import Control.Monad.Trans.Resource.Internal (MonadResource (..), ReleaseMap, ResourceT (..)) 21 | import Control.Monad.Trans.Resource (runResourceT) 22 | import Control.Monad.Trans.Control (MonadBaseControl (..)) 23 | 24 | import qualified Control.Monad.Logger as LegacyLogger 25 | import Control.Monad.Logger (MonadLogger (..), MonadLoggerIO (..), LogStr) 26 | import System.Log.FastLogger (fromLogStr) 27 | import qualified GHC.Stack as GS 28 | 29 | -- | @since 0.1.0.0 30 | deriving instance MonadCatch (RIO env) 31 | 32 | -- | @since 0.1.0.0 33 | deriving instance MonadMask (RIO env) 34 | 35 | -- | @since 0.1.0.0 36 | deriving instance MonadBase IO (RIO env) 37 | 38 | -- | @since 0.1.0.0 39 | instance MonadBaseControl IO (RIO env) where 40 | type StM (RIO env) a = a 41 | 42 | liftBaseWith = withRunInIO 43 | restoreM = return 44 | 45 | -- | @since 0.1.1.0 46 | instance Display LogStr where 47 | display = displayBytesUtf8 . fromLogStr 48 | 49 | -- | @since 0.1.1.0 50 | instance HasLogFunc env => MonadLogger (RIO env) where 51 | monadLoggerLog loc source level msg = 52 | let ?callStack = rioCallStack loc 53 | in logGeneric source (rioLogLevel level) (display $ LegacyLogger.toLogStr msg) 54 | 55 | -- | Do not let the generated function escape its RIO context. This may lead 56 | -- to log-related cleanup running /before/ the function is called. 57 | -- 58 | -- @since 0.1.2.0 59 | instance HasLogFunc env => MonadLoggerIO (RIO env) where 60 | askLoggerIO = do 61 | runInIO <- askRunInIO 62 | pure $ \loc source level str -> 63 | let ?callStack = rioCallStack loc 64 | in runInIO (logGeneric source (rioLogLevel level) (display str)) 65 | 66 | rioLogLevel :: LegacyLogger.LogLevel -> LogLevel 67 | rioLogLevel level = 68 | case level of 69 | LegacyLogger.LevelDebug -> LevelDebug 70 | LegacyLogger.LevelInfo -> LevelInfo 71 | LegacyLogger.LevelWarn -> LevelWarn 72 | LegacyLogger.LevelError -> LevelError 73 | LegacyLogger.LevelOther name -> LevelOther name 74 | 75 | rioCallStack :: LegacyLogger.Loc -> CallStack 76 | rioCallStack loc = GS.fromCallSiteList [("", GS.SrcLoc 77 | { GS.srcLocPackage = LegacyLogger.loc_package loc 78 | , GS.srcLocModule = LegacyLogger.loc_module loc 79 | , GS.srcLocFile = LegacyLogger.loc_filename loc 80 | , GS.srcLocStartLine = fst $ LegacyLogger.loc_start loc 81 | , GS.srcLocStartCol = snd $ LegacyLogger.loc_start loc 82 | , GS.srcLocEndLine = fst $ LegacyLogger.loc_end loc 83 | , GS.srcLocEndCol = snd $ LegacyLogger.loc_end loc 84 | })] 85 | 86 | -- | A collection of all of the registered resource cleanup actions. 87 | -- 88 | -- @since 0.1.0.0 89 | type ResourceMap = IORef ReleaseMap 90 | 91 | -- | Perform an action with a 'ResourceMap' 92 | -- 93 | -- @since 0.1.0.0 94 | withResourceMap :: MonadUnliftIO m => (ResourceMap -> m a) -> m a 95 | withResourceMap inner = 96 | withRunInIO $ \run -> runResourceT $ ResourceT $ run . inner 97 | 98 | -- | An environment with a 'ResourceMap' 99 | -- 100 | -- @since 0.1.0.0 101 | class HasResourceMap env where 102 | resourceMapL :: Lens' env ResourceMap 103 | instance HasResourceMap (IORef ReleaseMap) where 104 | resourceMapL = id 105 | instance HasResourceMap env => MonadResource (RIO env) where 106 | liftResourceT (ResourceT f) = view resourceMapL >>= liftIO . f 107 | -------------------------------------------------------------------------------- /rio-orphans/test/RIO/OrphansSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | module RIO.OrphansSpec (spec) where 3 | 4 | import Test.Hspec 5 | import RIO 6 | import RIO.Orphans 7 | import Control.Monad.Trans.Resource 8 | 9 | spec :: Spec 10 | spec = do 11 | it "success" $ do 12 | ref <- newIORef False 13 | withResourceMap $ \rm -> runRIO rm $ do 14 | void $ register $ writeIORef ref True 15 | readIORef ref `shouldReturn` True 16 | it "exceptions" $ do 17 | ref <- newIORef False 18 | void $ tryAny $ withResourceMap $ \rm -> runRIO rm $ do 19 | void $ register $ writeIORef ref True 20 | throwString "ignored" 21 | readIORef ref `shouldReturn` True 22 | it "no release" $ do 23 | ref <- newIORef False 24 | void $ tryAny $ withResourceMap $ \rm -> runRIO rm $ do 25 | () <- throwString "ignored" 26 | writeIORef ref True 27 | readIORef ref `shouldReturn` False 28 | -------------------------------------------------------------------------------- /rio-orphans/test/Spec.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -F -pgmF hspec-discover #-} 2 | -------------------------------------------------------------------------------- /rio/ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Changelog for rio 2 | 3 | ## 0.1.22.0 4 | 5 | * Expose `augmentPathMap'` 6 | 7 | ## 0.1.21.0 8 | 9 | * Fix minor bug in `augmentPathMap` on windows wrt [#234](https://github.com/commercialhaskell/rio/issues/234) not adhering to case-insensitive semantics 10 | 11 | ## 0.1.20.0 12 | 13 | * Export `UnliftIO.QSem` and `UnliftIO.QSemN` in `RIO` 14 | 15 | ## 0.1.19.0 16 | 17 | * Expose `fromLeft` and `fromRight` 18 | 19 | ## 0.1.18.0 20 | 21 | * Add colours to the `LogOption` constructor [#222](https://github.com/commercialhaskell/rio/pull/222) 22 | 23 | ## 0.1.17.0 24 | 25 | * Expose `Bifunctor`, `Bifoldable`, and `Bitraversable`. 26 | * The `first` and `second` functions exported by `RIO` formerly originated from 27 | `Control.Arrow`. They now come from `Bifunctor`. 28 | 29 | ## 0.1.16.0 30 | 31 | * Expand the number of `microlens` functions exported by the RIO prelude. 32 | * Add new module `RIO.Lens` which provides the rest of `microlens`. 33 | 34 | ## 0.1.15.1 35 | 36 | * Replace `canonicalizePath` with `makeAbsolute` [#217](https://github.com/commercialhaskell/rio/issues/217) 37 | 38 | ## 0.1.15.0 39 | 40 | * Include source in log messages 41 | 42 | ## 0.1.14.1 43 | 44 | * Support `unliftio-core` 0.2 45 | 46 | ## 0.1.14.0 47 | 48 | * Addition of `mkSimpleApp` 49 | * Addition of `lookupEnvFromContext` 50 | 51 | ## 0.1.13.0 52 | 53 | * Add `withLazyFileUtf8` 54 | * Add `mapRIO` 55 | * Add generic logger 56 | * Add `exeExtensions` and improve `findExecutable` on Windows [#205](https://github.com/commercialhaskell/rio/issues/205) 57 | 58 | ## 0.1.12.0 59 | 60 | * Add `logFormat` and `setLogFormat` for `LogOptions`. 61 | 62 | ## 0.1.11.0 63 | 64 | * Replace atomic and durable file writing functions with the ones from `unliftio`, see [#167](https://github.com/commercialhaskell/rio/pull/167) 65 | 66 | ## 0.1.10.0 67 | 68 | * Relax a bunch of `RIO.File` functions from `MonadUnliftIO` to `MonadIO` 69 | * Custom `Monoid` instance for `Utf8Builder` that matches semantics of the 70 | derived one, but doesn't break list fusion 71 | * Qualified import recommendations for `*.Partial`, `*.Unchecked`, `*.Unsafe` 72 | * Re-export `Data.Ord.Down` from `RIO.Prelude` 73 | * Addition of `RIO.NonEmpty` module 74 | * Addition of `RIO.NonEmpty.Partial` module 75 | * Export `NonEmpty` type and its constructor `(:|)` from RIO.Prelude.Types 76 | * Fix handling of non-ASCII characters in `logSticky` 77 | * Deprecate `withProcess` and `withProcess_`, add `withProcessWait`, `withProcessWait_`, `withProcessTerm`, and `withProcessTerm_` 78 | 79 | ## 0.1.9.2 80 | 81 | * Bring back re-export of `Monad.fail` from `RIO.Prelude`. 82 | 83 | ## 0.1.9.1 84 | 85 | * Remove accidental reexport of `Control.Applicative.empty` introduced in the previous release. 86 | * Functions from `Data.Data.Data` class are brought to the re-export list as well. 87 | 88 | ## 0.1.9.0 89 | 90 | * Add `Prelude.Exit` to export lifted versions of the exit functions from `System.Exit`. 91 | * Re-export the `Control.Monad.State.State` and `Control.Monad.State.StateT` types and related computation functions in `RIO.State`. 92 | * Re-export the `Control.Monad.Writer.Writer` and `Control.Monad.Writer.WriterT` types and related computation functions in `RIO.Writer`. 93 | * Re-export `pred`, `succ` in `RIO.Partial`. 94 | * Add `Semigroup` and `Monoid` instances for `RIO` 95 | * Add the `Deque` double-ended queue data type 96 | * Re-export `Data.Map.Strict.toAscList` and `Data.Map.Strict.toDescList` from `RIO.Map`. 97 | * Re-export `Data.Sequence.Seq` from `RIO`. 98 | * Addition of `RIO.Prelude` module 99 | * Addition of `RIO.Prelude.Types` module 100 | * Re-export `zipWith` and `runST` from `RIO.Prelude` 101 | * Re-export `Exception`, `MonadFail`, `Typeable` and `ST` from `RIO.Prelude.Types` 102 | * Switch to `MonadFail.fail` from `Monad.fail` and re-exported it from `RIO.Prelude` 103 | 104 | 105 | ## 0.1.8.0 106 | 107 | * Re-export `Control.Monad.State.modify`, `Control.Monad.State.modify'` and `Control.Monad.State.gets` in `RIO.State` 108 | 109 | ## 0.1.7.0 110 | 111 | * Addition of `textDisplay` to `Display` class. 112 | 113 | ## 0.1.6.0 114 | 115 | * Changed `logUseColor` to default to `False` on Windows, even when verbose and on the terminal 116 | * Add `RIO.File` module which offers a family of file handling functions 117 | (`withBinaryFileDurable`, `withBinaryFileDurableAtomic`, among others.) with 118 | better durability and atomicity guarantees 119 | 120 | ## 0.1.5.0 121 | 122 | * Re-export `Numeric.Natural.Natural` [#119](https://github.com/commercialhaskell/rio/issues/119) 123 | * Re-export `Data.Functor.<&>` from GHC 8.4+, falling back local definition for `base < 4.11` [#117](https://github.com/commercialhaskell/rio/issues/117) 124 | * Re-export `Data.Proxy.Proxy(..)` 125 | * Re-export `fromEnum` from RIO, export `toEnum`, `read` and `fromJust` from RIO.Partial 126 | * Add `noLogging` function to skip logging on specific sub-routines 127 | * Re-export `Control.Category.>>>` 128 | 129 | ## 0.1.4.0 130 | 131 | * Add `Const` and `Identity` 132 | * Add `Reader` and `runReader` 133 | * Add instances for `MonadWriter` and `MonadState` to `RIO` via mutable reference [#103](https://github.com/commercialhaskell/rio/issues/103) 134 | 135 | ## 0.1.3.0 136 | 137 | * Add `newLogFunc` function to create `LogFunc` records outside of a callback scope 138 | * Allow dynamic reloading of `logMinLevel` and `logVerboseFormat` for the `LogOptions` record 139 | * Add `foldMapM` 140 | * Add `headMaybe`, `lastMaybe`, `tailMaybe`, `initMaybe`, `maximumMaybe`, `minimumMaybe`, 141 | `maximumByMaybe`, `minimumByMaybe` functions to `RIO.List` module (issue #82) 142 | * Move non partial functions `scanr1` and `scanl1` from `RIO.List.Partial` to `RIO.List` (issue #82) 143 | * Add `SimpleApp` and `runSimpleApp` 144 | * Add `asIO` 145 | 146 | ## 0.1.2.0 147 | 148 | * Allow setting usage of code location in the log output 149 | 150 | ## 0.1.1.0 151 | 152 | * Move some accidentally included partial functions 153 | 154 | ## 0.1.0.0 155 | 156 | * Initial stable release 157 | 158 | ## 0.0 159 | 160 | __NOTE__ All releases beginning with 0.0 are considered 161 | experimental. Caveat emptor! 162 | -------------------------------------------------------------------------------- /rio/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Michael Snoyman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /rio/package.yaml: -------------------------------------------------------------------------------- 1 | name: rio 2 | version: 0.1.22.0 3 | synopsis: A standard library for Haskell 4 | description: See README and Haddocks at 5 | license: MIT 6 | author: Michael Snoyman 7 | maintainer: michael@snoyman.com 8 | github: commercialhaskell/rio 9 | category: Control 10 | 11 | extra-source-files: 12 | - README.md 13 | - ChangeLog.md 14 | 15 | dependencies: 16 | - base >= 4.12 && < 10 17 | - bytestring 18 | - containers 19 | - deepseq 20 | - directory 21 | - exceptions 22 | - filepath 23 | - hashable 24 | - microlens >= 0.4.2.0 25 | - microlens-mtl 26 | - mtl 27 | - primitive 28 | - text 29 | - time 30 | - typed-process >= 0.2.5.0 31 | - unliftio >= 0.2.14 32 | - unliftio-core 33 | - unordered-containers 34 | - vector 35 | 36 | # Just for preprocessor directives 37 | - process 38 | 39 | when: 40 | - condition: os(windows) 41 | then: 42 | cpp-options: -DWINDOWS 43 | dependencies: 44 | - Win32 45 | else: 46 | dependencies: 47 | - unix 48 | 49 | library: 50 | source-dirs: src/ 51 | exposed-modules: 52 | - RIO 53 | - RIO.ByteString 54 | - RIO.ByteString.Lazy 55 | - RIO.ByteString.Lazy.Partial 56 | - RIO.ByteString.Partial 57 | - RIO.Char 58 | - RIO.Char.Partial 59 | - RIO.Deque 60 | - RIO.Directory 61 | - RIO.File 62 | - RIO.FilePath 63 | - RIO.HashMap 64 | - RIO.HashMap.Partial 65 | - RIO.HashSet 66 | - RIO.Lens 67 | - RIO.List 68 | - RIO.List.Partial 69 | - RIO.Map 70 | - RIO.Map.Partial 71 | - RIO.Map.Unchecked 72 | - RIO.NonEmpty 73 | - RIO.NonEmpty.Partial 74 | - RIO.Partial 75 | - RIO.Prelude 76 | - RIO.Prelude.Simple 77 | - RIO.Prelude.Types 78 | - RIO.Process 79 | - RIO.Seq 80 | - RIO.Set 81 | - RIO.Set.Partial 82 | - RIO.Set.Unchecked 83 | - RIO.State 84 | - RIO.Text 85 | - RIO.Text.Lazy 86 | - RIO.Text.Lazy.Partial 87 | - RIO.Text.Partial 88 | - RIO.Time 89 | - RIO.Vector 90 | - RIO.Vector.Boxed 91 | - RIO.Vector.Boxed.Partial 92 | - RIO.Vector.Boxed.Unsafe 93 | - RIO.Vector.Partial 94 | - RIO.Vector.Storable 95 | - RIO.Vector.Storable.Partial 96 | - RIO.Vector.Storable.Unsafe 97 | - RIO.Vector.Unboxed 98 | - RIO.Vector.Unboxed.Partial 99 | - RIO.Vector.Unboxed.Unsafe 100 | - RIO.Vector.Unsafe 101 | - RIO.Writer 102 | 103 | other-modules: 104 | - RIO.Prelude.Display 105 | - RIO.Prelude.Exit 106 | - RIO.Prelude.Extra 107 | - RIO.Prelude.IO 108 | - RIO.Prelude.Lens 109 | - RIO.Prelude.Logger 110 | - RIO.Prelude.Reexports 111 | - RIO.Prelude.Renames 112 | - RIO.Prelude.RIO 113 | - RIO.Prelude.Text 114 | - RIO.Prelude.Trace 115 | - RIO.Prelude.URef 116 | 117 | tests: 118 | spec: 119 | source-dirs: test 120 | main: Spec.hs 121 | dependencies: 122 | - rio 123 | - hspec 124 | - QuickCheck 125 | verbatim: | 126 | build-tool-depends: 127 | hspec-discover:hspec-discover 128 | -------------------------------------------------------------------------------- /rio/src/RIO.hs: -------------------------------------------------------------------------------- 1 | module RIO 2 | ( 3 | -- * Custom @Prelude@ 4 | 5 | -- | One of the core features of @rio@ is that it can be used as a @Prelude@ 6 | -- replacement. Therefore it is best to disable the default `Prelude` with: 7 | -- [NoImplicitPrelude](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-NoImplicitPrelude) 8 | -- pragma: 9 | -- 10 | -- > {-# LANGUAGE NoImplicitPrelude #-} 11 | -- > import RIO 12 | -- 13 | -- Some functions not exported here can be found in "RIO.Partial": 14 | -- @fromJust@, @read@, @toEnum@, @pred@, @succ@. 15 | -- 16 | module RIO.Prelude 17 | , module RIO.Prelude.Types 18 | -- * The @RIO@ Monad 19 | 20 | , module MonadRIO 21 | -- ** @SimpleApp@ 22 | -- | If all you need is just some default environment that does basic logging and allows 23 | -- spawning processes, then you can use `SimpleApp`: 24 | -- 25 | -- > {-# LANGUAGE OverloadedStrings #-} 26 | -- > module Main where 27 | -- > 28 | -- > main :: IO () 29 | -- > main = 30 | -- > runSimpleApp $ do 31 | -- > logInfo "Hello World!" 32 | -- 33 | -- Note the 34 | -- [OverloadedStrings](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-OverloadedStrings) 35 | -- extension, which is enabled to simplify logging. 36 | , module RIO.Prelude.Simple 37 | -- * @MonadIO@ and @MonadUnliftIO@ 38 | , module Control.Monad.IO.Unlift 39 | -- * Logger 40 | -- $logging-intro 41 | , module RIO.Prelude.Logger 42 | -- * Display 43 | , module RIO.Prelude.Display 44 | -- * Optics 45 | -- | @microlens@-based Lenses, Traversals, etc. 46 | , module RIO.Prelude.Lens 47 | -- * Concurrency 48 | , UnliftIO.Concurrent.ThreadId 49 | , UnliftIO.Concurrent.myThreadId 50 | , UnliftIO.Concurrent.isCurrentThreadBound 51 | , UnliftIO.Concurrent.threadWaitRead 52 | , UnliftIO.Concurrent.threadWaitWrite 53 | , UnliftIO.Concurrent.threadDelay 54 | , RIO.Prelude.Renames.yieldThread 55 | -- ** Async 56 | , module UnliftIO.Async 57 | -- ** STM 58 | , module UnliftIO.STM 59 | -- ** Chan 60 | , module UnliftIO.Chan 61 | -- ** Timeout 62 | , module UnliftIO.Timeout 63 | -- * Exceptions 64 | , module UnliftIO.Exception 65 | -- | Re-exported from "Control.Monad.Catch": 66 | , Control.Monad.Catch.throwM 67 | -- * Files and handles 68 | , module UnliftIO.IO 69 | , module UnliftIO.Temporary 70 | , module RIO.Prelude.IO 71 | -- * Exit 72 | , module RIO.Prelude.Exit 73 | -- * Mutable Variables 74 | -- ** SomeRef 75 | , module SomeRef 76 | -- ** URef 77 | , module RIO.Prelude.URef 78 | -- ** IORef 79 | , module UnliftIO.IORef 80 | -- ** MVar 81 | , module UnliftIO.MVar 82 | -- ** QSem 83 | , module UnliftIO.QSem 84 | -- ** QSemN 85 | , module UnliftIO.QSemN 86 | -- ** Memoize 87 | , module UnliftIO.Memoize 88 | -- ** Deque 89 | , module RIO.Deque 90 | 91 | -- * Debugging 92 | , module RIO.Prelude.Trace 93 | ) where 94 | 95 | import qualified Control.Monad.Catch (MonadThrow(..)) 96 | import RIO.Deque 97 | import RIO.Prelude 98 | import RIO.Prelude.Display 99 | import RIO.Prelude.Exit 100 | import RIO.Prelude.Extra 101 | import RIO.Prelude.IO 102 | import RIO.Prelude.Lens 103 | import RIO.Prelude.Logger 104 | import RIO.Prelude.Renames 105 | import RIO.Prelude.RIO as MonadRIO (RIO(..), liftRIO, runRIO) 106 | import RIO.Prelude.RIO as SomeRef hiding (RIO(..), liftRIO, runRIO) 107 | import RIO.Prelude.Simple 108 | import RIO.Prelude.Text 109 | import RIO.Prelude.Trace 110 | import RIO.Prelude.Types 111 | import RIO.Prelude.URef 112 | import Control.Monad.IO.Unlift 113 | import UnliftIO.Async 114 | import UnliftIO.Chan 115 | import UnliftIO.Exception 116 | import UnliftIO.IO 117 | import UnliftIO.IORef 118 | import UnliftIO.Memoize 119 | import UnliftIO.MVar 120 | import UnliftIO.QSem 121 | import UnliftIO.QSemN 122 | import UnliftIO.STM 123 | import UnliftIO.Temporary 124 | import UnliftIO.Timeout 125 | import UnliftIO.Concurrent 126 | 127 | -------------------------------------------------------------------------------- 128 | -- $logging-intro 129 | -- 130 | -- The logging system in RIO is built upon "log functions", which are 131 | -- accessed in RIO's environment via a class like "has log 132 | -- function". There are two provided: 133 | -- 134 | -- * In the common case: for logging plain text (via 'Utf8Builder') 135 | -- efficiently, there is 'LogFunc', which can be created via 136 | -- 'withLogFunc', and is accessed via 'HasLogFunc'. This provides 137 | -- all the classical logging facilities: timestamped text output 138 | -- with log levels and colors (if terminal-supported) to the 139 | -- terminal. We log output via 'logInfo', 'logDebug', etc. 140 | -- 141 | -- * In the advanced case: where logging takes on a more semantic 142 | -- meaning and the logs need to be digested, acted upon, translated 143 | -- or serialized upstream (to e.g. a JSON logging server), we have 144 | -- 'GLogFunc' (as in "generic log function"), and is accessed via 145 | -- 'HasGLogFunc'. In this case, we log output via 'glog'. See the 146 | -- Type-generic logger section for more information. 147 | -------------------------------------------------------------------------------- /rio/src/RIO/ByteString.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | Strict @ByteString@. Import as: 4 | -- 5 | -- > import qualified RIO.ByteString as B 6 | -- 7 | -- This module does not export any partial functions. For those, see 8 | -- "RIO.ByteString.Partial" 9 | module RIO.ByteString 10 | ( module Data.ByteString 11 | , module RIO.ByteString 12 | ) where 13 | 14 | import Data.ByteString hiding (head, last, tail, init, foldl1, foldl1', foldr1, foldr1', maximum, minimum, findSubstring, findSubstrings, packCString, packCStringLen, useAsCString, useAsCStringLen, getLine, getContents, putStr, putStrLn, interact, readFile, writeFile, appendFile, hGetLine, hGetContents, hGet, hGetSome, hGetNonBlocking, hPut, hPutNonBlocking, hPutStr, hPutStrLn, breakByte) 15 | import qualified Data.ByteString as B 16 | import RIO 17 | import Foreign.C.String (CString, CStringLen) 18 | 19 | -- | Lifted 'B.packCString' 20 | packCString :: MonadIO m => CString -> m ByteString 21 | packCString = liftIO . B.packCString 22 | 23 | -- | Lifted 'B.packCStringLen' 24 | packCStringLen :: MonadIO m => CStringLen -> m ByteString 25 | packCStringLen = liftIO . B.packCStringLen 26 | 27 | -- | Unlifted 'B.useAsCString' 28 | useAsCString :: MonadUnliftIO m => ByteString -> (CString -> m a) -> m a 29 | useAsCString bs inner = withRunInIO $ \run -> B.useAsCString bs $ run . inner 30 | 31 | -- | Unlifted 'B.useAsCStringLen' 32 | useAsCStringLen :: MonadUnliftIO m => ByteString -> (CStringLen -> m a) -> m a 33 | useAsCStringLen bs inner = withRunInIO $ \run -> B.useAsCStringLen bs $ run . inner 34 | 35 | -- | Lifted 'B.getLine' 36 | getLine :: MonadIO m => m ByteString 37 | getLine = liftIO B.getLine 38 | 39 | -- | Lifted 'B.getContents' 40 | getContents :: MonadIO m => m ByteString 41 | getContents = liftIO B.getContents 42 | 43 | -- | Lifted 'B.putStr' 44 | putStr :: MonadIO m => ByteString -> m () 45 | putStr = liftIO . B.putStr 46 | 47 | -- | Lifted 'B.interact' 48 | interact :: MonadIO m => (ByteString -> ByteString) -> m () 49 | interact = liftIO . B.interact 50 | 51 | -- | Lifted 'B.readFile' 52 | readFile :: MonadIO m => FilePath -> m ByteString 53 | readFile = liftIO . B.readFile 54 | 55 | -- | Lifted 'B.writeFile' 56 | writeFile :: MonadIO m => FilePath -> ByteString -> m () 57 | writeFile fp = liftIO . B.writeFile fp 58 | 59 | -- | Lifted 'B.appendFile' 60 | appendFile :: MonadIO m => FilePath -> ByteString -> m () 61 | appendFile fp = liftIO . B.appendFile fp 62 | 63 | -- | Lifted 'B.hGetLine' 64 | hGetLine :: MonadIO m => Handle -> m ByteString 65 | hGetLine = liftIO . B.hGetLine 66 | 67 | -- | Lifted 'B.hGetContents' 68 | hGetContents :: MonadIO m => Handle -> m ByteString 69 | hGetContents = liftIO . B.hGetContents 70 | 71 | -- | Lifted 'B.hGet' 72 | hGet :: MonadIO m => Handle -> Int -> m ByteString 73 | hGet h = liftIO . B.hGet h 74 | 75 | -- | Lifted 'B.hGetSome' 76 | hGetSome :: MonadIO m => Handle -> Int -> m ByteString 77 | hGetSome h = liftIO . B.hGetSome h 78 | 79 | -- | Lifted 'B.hGetNonBlocking' 80 | hGetNonBlocking :: MonadIO m => Handle -> Int -> m ByteString 81 | hGetNonBlocking h = liftIO . B.hGetNonBlocking h 82 | 83 | -- | Lifted 'B.hPut' 84 | hPut :: MonadIO m => Handle -> ByteString -> m () 85 | hPut h = liftIO . B.hPut h 86 | 87 | -- | Lifted 'B.hPutNonBlocking' 88 | hPutNonBlocking :: MonadIO m => Handle -> ByteString -> m ByteString 89 | hPutNonBlocking h = liftIO . B.hPutNonBlocking h 90 | 91 | -- | Lifted 'B.hPutStr' 92 | hPutStr :: MonadIO m => Handle -> ByteString -> m () 93 | hPutStr h = liftIO . B.hPutStr h 94 | -------------------------------------------------------------------------------- /rio/src/RIO/ByteString/Lazy.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | Lazy @ByteString@. Import as: 4 | -- 5 | -- > import qualified RIO.ByteString.Lazy as BL 6 | -- 7 | -- This module does not export any partial functions. For those, see 8 | -- "RIO.ByteString.Lazy.Partial" 9 | module RIO.ByteString.Lazy 10 | ( 11 | -- * The @ByteString@ type 12 | Data.ByteString.Lazy.ByteString 13 | 14 | -- * Introducing and eliminating 'ByteString's 15 | , Data.ByteString.Lazy.empty 16 | , Data.ByteString.Lazy.singleton 17 | , Data.ByteString.Lazy.pack 18 | , Data.ByteString.Lazy.unpack 19 | , Data.ByteString.Lazy.fromStrict 20 | , Data.ByteString.Lazy.toStrict 21 | , Data.ByteString.Lazy.fromChunks 22 | , Data.ByteString.Lazy.toChunks 23 | , Data.ByteString.Lazy.foldrChunks 24 | , Data.ByteString.Lazy.foldlChunks 25 | 26 | -- * Basic interface 27 | , Data.ByteString.Lazy.cons 28 | , Data.ByteString.Lazy.cons' 29 | , Data.ByteString.Lazy.snoc 30 | , Data.ByteString.Lazy.append 31 | , Data.ByteString.Lazy.uncons 32 | , Data.ByteString.Lazy.unsnoc 33 | , Data.ByteString.Lazy.null 34 | , Data.ByteString.Lazy.length 35 | 36 | -- * Transforming ByteStrings 37 | , Data.ByteString.Lazy.map 38 | , Data.ByteString.Lazy.reverse 39 | , Data.ByteString.Lazy.intersperse 40 | , Data.ByteString.Lazy.intercalate 41 | , Data.ByteString.Lazy.transpose 42 | 43 | -- * Reducing 'ByteString's (folds) 44 | , Data.ByteString.Lazy.foldl 45 | , Data.ByteString.Lazy.foldl' 46 | , Data.ByteString.Lazy.foldr 47 | 48 | -- ** Special folds 49 | , Data.ByteString.Lazy.concat 50 | , Data.ByteString.Lazy.concatMap 51 | , Data.ByteString.Lazy.any 52 | , Data.ByteString.Lazy.all 53 | 54 | -- * Building ByteStrings 55 | -- ** Scans 56 | , Data.ByteString.Lazy.scanl 57 | 58 | -- ** Accumulating maps 59 | , Data.ByteString.Lazy.mapAccumL 60 | , Data.ByteString.Lazy.mapAccumR 61 | 62 | -- ** Infinite ByteStrings 63 | , Data.ByteString.Lazy.repeat 64 | , Data.ByteString.Lazy.replicate 65 | , Data.ByteString.Lazy.cycle 66 | , Data.ByteString.Lazy.iterate 67 | 68 | -- ** Unfolding ByteStrings 69 | , Data.ByteString.Lazy.unfoldr 70 | 71 | -- * Substrings 72 | -- ** Breaking strings 73 | , Data.ByteString.Lazy.take 74 | , Data.ByteString.Lazy.drop 75 | , Data.ByteString.Lazy.splitAt 76 | , Data.ByteString.Lazy.takeWhile 77 | , Data.ByteString.Lazy.dropWhile 78 | , Data.ByteString.Lazy.span 79 | , Data.ByteString.Lazy.break 80 | , Data.ByteString.Lazy.group 81 | , Data.ByteString.Lazy.groupBy 82 | , Data.ByteString.Lazy.inits 83 | , Data.ByteString.Lazy.tails 84 | , Data.ByteString.Lazy.stripPrefix 85 | , Data.ByteString.Lazy.stripSuffix 86 | 87 | -- ** Breaking into many substrings 88 | , Data.ByteString.Lazy.split 89 | , Data.ByteString.Lazy.splitWith 90 | 91 | -- * Predicates 92 | , Data.ByteString.Lazy.isPrefixOf 93 | , Data.ByteString.Lazy.isSuffixOf 94 | 95 | -- * Search ByteStrings 96 | -- ** Searching by equality 97 | , Data.ByteString.Lazy.elem 98 | , Data.ByteString.Lazy.notElem 99 | 100 | -- ** Searching with a predicate 101 | , Data.ByteString.Lazy.find 102 | , Data.ByteString.Lazy.filter 103 | , Data.ByteString.Lazy.partition 104 | 105 | -- * Indexing ByteStrings 106 | , Data.ByteString.Lazy.index 107 | , Data.ByteString.Lazy.elemIndex 108 | , Data.ByteString.Lazy.elemIndexEnd 109 | , Data.ByteString.Lazy.elemIndices 110 | , Data.ByteString.Lazy.findIndex 111 | , Data.ByteString.Lazy.findIndices 112 | , Data.ByteString.Lazy.count 113 | 114 | -- * Zipping and unzipping ByteStrings 115 | , Data.ByteString.Lazy.zip 116 | , Data.ByteString.Lazy.zipWith 117 | , Data.ByteString.Lazy.unzip 118 | 119 | -- * Low level conversions 120 | -- ** Copying ByteStrings 121 | , Data.ByteString.Lazy.copy 122 | 123 | -- * I\/O with 'ByteString's 124 | -- ** Standard input and output 125 | , getContents 126 | , putStr 127 | , putStrLn 128 | , interact 129 | 130 | -- ** Files 131 | , readFile 132 | , writeFile 133 | , appendFile 134 | 135 | -- ** I\/O with Handles 136 | , hGetContents 137 | , hGet 138 | , hGetNonBlocking 139 | , hPut 140 | , hPutNonBlocking 141 | , hPutStr 142 | ) where 143 | 144 | import Data.ByteString.Lazy hiding 145 | ( 146 | getContents 147 | , putStr 148 | , putStrLn 149 | , interact 150 | , readFile 151 | , writeFile 152 | , appendFile 153 | , hGetContents 154 | , hGet 155 | , hGetNonBlocking 156 | , hPut 157 | , hPutNonBlocking 158 | , hPutStr 159 | ) 160 | import qualified Data.ByteString.Lazy 161 | import qualified Data.ByteString.Lazy.Char8 162 | import RIO 163 | 164 | -- | Lifted 'Data.ByteString.Lazy.getContents' 165 | getContents :: MonadIO m => m LByteString 166 | getContents = liftIO Data.ByteString.Lazy.getContents 167 | 168 | -- | Lifted 'Data.ByteString.Lazy.putStr' 169 | putStr :: MonadIO m => LByteString -> m () 170 | putStr = liftIO . Data.ByteString.Lazy.putStr 171 | 172 | -- | Lifted 'Data.ByteString.Lazy.putStrLn' 173 | putStrLn :: MonadIO m => LByteString -> m () 174 | putStrLn = liftIO . Data.ByteString.Lazy.Char8.putStrLn 175 | 176 | -- | Lifted 'Data.ByteString.Lazy.interact' 177 | interact :: MonadIO m => (LByteString -> LByteString) -> m () 178 | interact = liftIO . Data.ByteString.Lazy.interact 179 | 180 | -- | Lifted 'Data.ByteString.Lazy.readFile' 181 | readFile :: MonadIO m => FilePath -> m LByteString 182 | readFile = liftIO . Data.ByteString.Lazy.readFile 183 | 184 | -- | Lifted 'Data.ByteString.Lazy.writeFile' 185 | writeFile :: MonadIO m => FilePath -> LByteString -> m () 186 | writeFile fp contents = 187 | liftIO $ Data.ByteString.Lazy.writeFile fp contents 188 | 189 | -- | Lifted 'Data.ByteString.Lazy.appendFile' 190 | appendFile :: MonadIO m => FilePath -> LByteString -> m () 191 | appendFile fp = liftIO . Data.ByteString.Lazy.appendFile fp 192 | 193 | -- | Lifted 'Data.ByteString.Lazy.hGet' 194 | hGet :: MonadIO m => Handle -> Int -> m LByteString 195 | hGet handle' count' = liftIO $ Data.ByteString.Lazy.hGet handle' count' 196 | 197 | -- | Lifted 'Data.ByteString.Lazy.hGetContents' 198 | hGetContents :: MonadIO m => Handle -> m LByteString 199 | hGetContents = liftIO . Data.ByteString.Lazy.hGetContents 200 | 201 | -- | Lifted 'Data.ByteString.Lazy.hGetNonBlocking' 202 | hGetNonBlocking :: MonadIO m => Handle -> Int -> m LByteString 203 | hGetNonBlocking h = liftIO . Data.ByteString.Lazy.hGetNonBlocking h 204 | 205 | -- | Lifted 'Data.ByteString.Lazy.hPut' 206 | hPut :: MonadIO m => Handle -> LByteString -> m () 207 | hPut h = liftIO . Data.ByteString.Lazy.hPut h 208 | 209 | -- | Lifted 'Data.ByteString.Lazy.hPutNonBlocking' 210 | hPutNonBlocking :: MonadIO m => Handle -> LByteString -> m LByteString 211 | hPutNonBlocking h = liftIO . Data.ByteString.Lazy.hPutNonBlocking h 212 | 213 | -- | Lifted 'Data.ByteString.Lazy.hPutStr' 214 | hPutStr :: MonadIO m => Handle -> LByteString -> m () 215 | hPutStr h = liftIO . Data.ByteString.Lazy.hPutStr h 216 | -------------------------------------------------------------------------------- /rio/src/RIO/ByteString/Lazy/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Lazy @ByteString@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.ByteString.Lazy.Partial as BL' 4 | module RIO.ByteString.Lazy.Partial 5 | ( 6 | -- * Basic interface 7 | Data.ByteString.Lazy.head 8 | , Data.ByteString.Lazy.last 9 | , Data.ByteString.Lazy.tail 10 | , Data.ByteString.Lazy.init 11 | 12 | -- * Reducing 'ByteString's (folds) 13 | , Data.ByteString.Lazy.foldl1 14 | , Data.ByteString.Lazy.foldl1' 15 | , Data.ByteString.Lazy.foldr1 16 | 17 | -- ** Special folds 18 | , Data.ByteString.Lazy.maximum 19 | , Data.ByteString.Lazy.minimum 20 | ) where 21 | 22 | import qualified Data.ByteString.Lazy 23 | -------------------------------------------------------------------------------- /rio/src/RIO/ByteString/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Strict @ByteString@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.ByteString.Partial as B' 4 | module RIO.ByteString.Partial 5 | ( 6 | -- * Basic interface 7 | Data.ByteString.head 8 | , Data.ByteString.last 9 | , Data.ByteString.tail 10 | , Data.ByteString.init 11 | 12 | -- * Reducing 'ByteString's (folds) 13 | , Data.ByteString.foldl1 14 | , Data.ByteString.foldl1' 15 | , Data.ByteString.foldr1 16 | , Data.ByteString.foldr1' 17 | 18 | -- * Special folds 19 | , Data.ByteString.maximum 20 | , Data.ByteString.minimum 21 | ) where 22 | 23 | import qualified Data.ByteString 24 | -------------------------------------------------------------------------------- /rio/src/RIO/Char.hs: -------------------------------------------------------------------------------- 1 | -- | Unicode @Char@. Import as: 2 | -- 3 | -- > import qualified RIO.Char as C 4 | -- 5 | -- This module does not export any partial functions. For those, see 6 | -- "RIO.Char.Partial" 7 | module RIO.Char 8 | ( 9 | Data.Char.Char 10 | 11 | -- * Character classification 12 | -- | Unicode characters are divided into letters, Data.Char.numbers, marks, 13 | -- punctuation, Data.Char.symbols, separators (including spaces) and others 14 | -- (including control characters). 15 | , Data.Char.isControl 16 | , Data.Char.isSpace 17 | , Data.Char.isLower 18 | , Data.Char.isUpper 19 | , Data.Char.isAlpha 20 | , Data.Char.isAlphaNum 21 | , Data.Char.isPrint 22 | , Data.Char.isDigit 23 | , Data.Char.isOctDigit 24 | , Data.Char.isHexDigit 25 | , Data.Char.isLetter 26 | , Data.Char.isMark 27 | , Data.Char.isNumber 28 | , Data.Char.isPunctuation 29 | , Data.Char.isSymbol 30 | , Data.Char.isSeparator 31 | 32 | -- ** Subranges 33 | , Data.Char.isAscii 34 | , Data.Char.isLatin1 35 | , Data.Char.isAsciiUpper 36 | , Data.Char.isAsciiLower 37 | 38 | -- ** Unicode general categories 39 | , Data.Char.GeneralCategory(..) 40 | , Data.Char.generalCategory 41 | 42 | -- * Case conversion 43 | , Data.Char.toUpper 44 | , Data.Char.toLower 45 | , Data.Char.toTitle 46 | 47 | -- * Numeric representations 48 | , Data.Char.ord 49 | 50 | -- * String representations 51 | , Data.Char.showLitChar 52 | , Data.Char.lexLitChar 53 | , Data.Char.readLitChar 54 | ) where 55 | 56 | import qualified Data.Char 57 | -------------------------------------------------------------------------------- /rio/src/RIO/Char/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Unicode @Char@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Char.Partial as C' 4 | module RIO.Char.Partial 5 | ( 6 | -- * Single digit characters 7 | Data.Char.digitToInt 8 | , Data.Char.intToDigit 9 | 10 | -- * Numeric representations 11 | , Data.Char.chr 12 | ) where 13 | 14 | import qualified Data.Char 15 | -------------------------------------------------------------------------------- /rio/src/RIO/Deque.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | module RIO.Deque 3 | ( -- * Types 4 | Deque 5 | , UDeque 6 | , SDeque 7 | , BDeque 8 | -- * Operations 9 | , newDeque 10 | , getDequeSize 11 | , popFrontDeque 12 | , popBackDeque 13 | , pushFrontDeque 14 | , pushBackDeque 15 | , foldlDeque 16 | , foldrDeque 17 | , dequeToList 18 | , dequeToVector 19 | , freezeDeque 20 | -- * Inference helpers 21 | , asUDeque 22 | , asSDeque 23 | , asBDeque 24 | ) where 25 | 26 | import RIO.Prelude.Reexports 27 | import Control.Exception (assert) 28 | import Control.Monad (liftM) 29 | import qualified Data.Vector.Generic as VG 30 | import qualified Data.Vector.Generic.Mutable as V 31 | import qualified Data.Vector.Mutable as B 32 | import qualified Data.Vector.Storable.Mutable as S 33 | import qualified Data.Vector.Unboxed.Mutable as U 34 | import Data.Primitive.MutVar 35 | 36 | data DequeState v s a = DequeState 37 | !(v s a) 38 | {-# UNPACK #-} !Int -- start 39 | {-# UNPACK #-} !Int -- size 40 | 41 | -- | A double-ended queue supporting any underlying vector type and any monad. 42 | -- 43 | -- This implements a circular double-ended queue with exponential growth. 44 | -- 45 | -- @since 0.1.9.0 46 | newtype Deque v s a = Deque (MutVar s (DequeState v s a)) 47 | 48 | -- | A 'Deque' specialized to unboxed vectors. 49 | -- 50 | -- @since 0.1.9.0 51 | type UDeque = Deque U.MVector 52 | 53 | -- | A 'Deque' specialized to storable vectors. 54 | -- 55 | -- @since 0.1.9.0 56 | type SDeque = Deque S.MVector 57 | 58 | -- | A 'Deque' specialized to boxed vectors. 59 | -- 60 | -- @since 0.1.9.0 61 | type BDeque = Deque B.MVector 62 | 63 | -- | Helper function to assist with type inference, forcing usage of 64 | -- an unboxed vector. 65 | -- 66 | -- @since 0.1.9.0 67 | asUDeque :: UDeque s a -> UDeque s a 68 | asUDeque = id 69 | 70 | -- | Helper function to assist with type inference, forcing usage of a 71 | -- storable vector. 72 | -- 73 | -- @since 0.1.9.0 74 | asSDeque :: SDeque s a -> SDeque s a 75 | asSDeque = id 76 | 77 | -- | Helper function to assist with type inference, forcing usage of a 78 | -- boxed vector. 79 | -- 80 | -- @since 0.1.9.0 81 | asBDeque :: BDeque s a -> BDeque s a 82 | asBDeque = id 83 | 84 | -- | Create a new, empty 'Deque' 85 | -- 86 | -- @since 0.1.9.0 87 | newDeque 88 | :: (V.MVector v a, PrimMonad m) 89 | => m (Deque v (PrimState m) a) 90 | newDeque = do 91 | v <- V.new baseSize 92 | liftM Deque $ newMutVar (DequeState v 0 0) 93 | where 94 | baseSize = 32 95 | {-# INLINE newDeque #-} 96 | 97 | 98 | -- | /O(1)/ - Get the number of elements that is currently in the `Deque` 99 | -- 100 | -- @since 0.1.9.0 101 | getDequeSize :: PrimMonad m => Deque v (PrimState m) a -> m Int 102 | getDequeSize (Deque var) = do 103 | DequeState _ _ size <- readMutVar var 104 | pure size 105 | {-# INLINE getDequeSize #-} 106 | 107 | 108 | -- | Pop the first value from the beginning of the 'Deque' 109 | -- 110 | -- @since 0.1.9.0 111 | popFrontDeque 112 | :: (V.MVector v a, PrimMonad m) 113 | => Deque v (PrimState m) a 114 | -> m (Maybe a) 115 | popFrontDeque (Deque var) = do 116 | DequeState v start size <- readMutVar var 117 | if size == 0 118 | then return Nothing 119 | else do 120 | x <- V.unsafeRead v start 121 | let start' = start + 1 122 | start'' 123 | | start' >= V.length v = 0 124 | | otherwise = start' 125 | writeMutVar var $! DequeState v start'' (size - 1) 126 | return $! Just x 127 | {-# INLINE popFrontDeque #-} 128 | 129 | -- | Pop the first value from the end of the 'Deque' 130 | -- 131 | -- @since 0.1.9.0 132 | popBackDeque 133 | :: (V.MVector v a, PrimMonad m) 134 | => Deque v (PrimState m) a 135 | -> m (Maybe a) 136 | popBackDeque (Deque var) = do 137 | DequeState v start size <- readMutVar var 138 | if size == 0 139 | then return Nothing 140 | else do 141 | let size' = size - 1 142 | end = start + size' 143 | end' 144 | | end >= V.length v = end - V.length v 145 | | otherwise = end 146 | x <- V.unsafeRead v end' 147 | writeMutVar var $! DequeState v start size' 148 | return $! Just x 149 | {-# INLINE popBackDeque #-} 150 | 151 | -- | Push a new value to the beginning of the 'Deque' 152 | -- 153 | -- @since 0.1.9.0 154 | pushFrontDeque 155 | :: (V.MVector v a, PrimMonad m) 156 | => Deque v (PrimState m) a 157 | -> a 158 | -> m () 159 | pushFrontDeque (Deque var) x = do 160 | DequeState v start size <- readMutVar var 161 | inner v start size 162 | where 163 | inner v start size = do 164 | if size >= V.length v 165 | then newVector v start size inner 166 | else do 167 | let size' = size + 1 168 | start' = (start - 1) `rem` V.length v 169 | start'' 170 | | start' < 0 = V.length v + start' 171 | | otherwise = start' 172 | V.unsafeWrite v start'' x 173 | writeMutVar var $! DequeState v start'' size' 174 | {-# INLINE pushFrontDeque #-} 175 | 176 | -- | Push a new value to the end of the 'Deque' 177 | -- 178 | -- @since 0.1.9.0 179 | pushBackDeque 180 | :: (V.MVector v a, PrimMonad m) 181 | => Deque v (PrimState m) a 182 | -> a 183 | -> m () 184 | pushBackDeque (Deque var) x = do 185 | DequeState v start size <- readMutVar var 186 | inner v start size 187 | where 188 | inner v start size = do 189 | if size >= V.length v 190 | then newVector v start size inner 191 | else do 192 | let end = start + size 193 | end' 194 | | end >= V.length v = end - V.length v 195 | | otherwise = end 196 | V.unsafeWrite v end' x 197 | writeMutVar var $! DequeState v start (size + 1) 198 | {-# INLINE pushBackDeque #-} 199 | 200 | -- | Fold over a 'Deque', starting at the beginning. Does not modify the 'Deque'. 201 | -- 202 | -- @since 0.1.9.0 203 | foldlDeque 204 | :: (V.MVector v a, PrimMonad m) 205 | => (acc -> a -> m acc) 206 | -> acc 207 | -> Deque v (PrimState m) a 208 | -> m acc 209 | foldlDeque f acc0 (Deque var) = do 210 | DequeState v start size <- readMutVar var 211 | let loop idx acc 212 | | idx >= size = pure acc 213 | | otherwise = do 214 | let idxPlusStart = idx + start 215 | idx' 216 | | idxPlusStart >= V.length v = idxPlusStart - V.length v 217 | | otherwise = idxPlusStart 218 | a <- V.unsafeRead v idx' 219 | acc' <- f acc a 220 | loop (idx + 1) $! acc' 221 | loop 0 acc0 222 | 223 | 224 | -- | Fold over a 'Deque', starting at the end. Does not modify the 'Deque'. 225 | -- 226 | -- @since 0.1.9.0 227 | foldrDeque 228 | :: (V.MVector v a, PrimMonad m) 229 | => (a -> acc -> m acc) 230 | -> acc 231 | -> Deque v (PrimState m) a 232 | -> m acc 233 | foldrDeque f acc0 (Deque var) = do 234 | DequeState v start size <- readMutVar var 235 | let loop idx acc 236 | | idx < 0 = pure acc 237 | | otherwise = do 238 | let idxPlusStart = idx + start 239 | idx' 240 | | idxPlusStart >= V.length v = idxPlusStart - V.length v 241 | | otherwise = idxPlusStart 242 | a <- V.unsafeRead v idx' 243 | acc' <- f a acc 244 | loop (idx - 1) $! acc' 245 | loop (size - 1) acc0 246 | 247 | -- | Convert a 'Deque' into a list. Does not modify the 'Deque'. 248 | -- 249 | -- @since 0.1.9.0 250 | dequeToList 251 | :: (V.MVector v a, PrimMonad m) 252 | => Deque v (PrimState m) a 253 | -> m [a] 254 | dequeToList = foldrDeque (\a rest -> pure $ a : rest) [] 255 | {-# INLINE dequeToList #-} 256 | 257 | 258 | -- | Convert to an immutable vector of any type. If resulting pure vector corresponds to the mutable 259 | -- one used by the `Deque`, it will be more efficient to use `freezeDeque` instead. 260 | -- 261 | -- ==== __Example__ 262 | -- 263 | -- >>> :set -XTypeApplications 264 | -- >>> import qualified RIO.Vector.Unboxed as U 265 | -- >>> import qualified RIO.Vector.Storable as S 266 | -- >>> d <- newDeque @U.MVector @Int 267 | -- >>> mapM_ (pushFrontDeque d) [0..10] 268 | -- >>> dequeToVector @S.Vector d 269 | -- [10,9,8,7,6,5,4,3,2,1,0] 270 | -- 271 | -- @since 0.1.9.0 272 | dequeToVector :: (VG.Vector v' a, V.MVector v a, PrimMonad m) 273 | => Deque v (PrimState m) a -> m (v' a) 274 | dequeToVector dq = do 275 | size <- getDequeSize dq 276 | mv <- V.unsafeNew size 277 | foldlDeque (\i e -> V.unsafeWrite mv i e >> pure (i+1)) 0 dq 278 | VG.unsafeFreeze mv 279 | 280 | 281 | newVector :: (PrimMonad m, V.MVector v a) 282 | => v (PrimState m) a 283 | -> Int 284 | -> Int 285 | -> (v (PrimState m) a -> Int -> Int -> m b) 286 | -> m b 287 | newVector v size2 sizeOrig f = assert (sizeOrig == V.length v) $ do 288 | v' <- V.unsafeNew (V.length v * 2) 289 | let size1 = V.length v - size2 290 | V.unsafeCopy 291 | (V.unsafeTake size1 v') 292 | (V.unsafeSlice size2 size1 v) 293 | V.unsafeCopy 294 | (V.unsafeSlice size1 size2 v') 295 | (V.unsafeTake size2 v) 296 | f v' 0 sizeOrig 297 | {-# INLINE newVector #-} 298 | 299 | 300 | -- | Yield an immutable copy of the underlying mutable vector. The difference from `dequeToVector` 301 | -- is that the the copy will be performed with a more efficient @memcpy@, rather than element by 302 | -- element. The downside is that the resulting vector type must be the one that corresponds to the 303 | -- mutable one that is used in the `Deque`. 304 | -- 305 | -- ==== __Example__ 306 | -- 307 | -- >>> :set -XTypeApplications 308 | -- >>> import qualified RIO.Vector.Unboxed as U 309 | -- >>> d <- newDeque @U.MVector @Int 310 | -- >>> mapM_ (pushFrontDeque d) [0..10] 311 | -- >>> freezeDeque @U.Vector d 312 | -- [10,9,8,7,6,5,4,3,2,1,0] 313 | -- 314 | -- @since 0.1.9.0 315 | freezeDeque :: 316 | (VG.Vector v a, PrimMonad m) 317 | => Deque (VG.Mutable v) (PrimState m) a 318 | -> m (v a) 319 | freezeDeque (Deque var) = do 320 | state@(DequeState v _ size) <- readMutVar var 321 | v' <- V.unsafeNew size 322 | makeCopy v' state 323 | VG.unsafeFreeze v' 324 | 325 | 326 | makeCopy :: 327 | (V.MVector v a, PrimMonad m) 328 | => v (PrimState m) a 329 | -> DequeState v (PrimState m) a 330 | -> m () 331 | makeCopy v' (DequeState v start size) = do 332 | let size1 = min size (V.length v - start) 333 | size2 = size - size1 334 | V.unsafeCopy 335 | (V.unsafeTake size1 v') 336 | (V.unsafeSlice start size1 v) 337 | when (size > size1) $ V.unsafeCopy 338 | (V.unsafeSlice size1 size2 v') 339 | (V.unsafeTake size2 v) 340 | {-# INLINE makeCopy #-} 341 | -------------------------------------------------------------------------------- /rio/src/RIO/Directory.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# LANGUAGE NoImplicitPrelude #-} 3 | module RIO.Directory 4 | ( module UnliftIO.Directory 5 | ) where 6 | 7 | import UnliftIO.Directory 8 | -------------------------------------------------------------------------------- /rio/src/RIO/File.hs: -------------------------------------------------------------------------------- 1 | {-| 2 | 3 | == Rationale 4 | 5 | This module offers functions to handle files that offer better durability and/or 6 | atomicity. 7 | 8 | See "UnliftIO.IO.File" for the rationale behind this module, since all of the functions 9 | were moved upstream and are now simply re-exported from here. 10 | 11 | @since 0.1.6 12 | -} 13 | module RIO.File 14 | ( -- * Regular 15 | withBinaryFile 16 | , writeBinaryFile 17 | -- * Atomic 18 | , withBinaryFileAtomic 19 | , writeBinaryFileAtomic 20 | -- * Durable 21 | , withBinaryFileDurable 22 | , writeBinaryFileDurable 23 | , ensureFileDurable 24 | -- * Durable and Atomic 25 | , withBinaryFileDurableAtomic 26 | , writeBinaryFileDurableAtomic 27 | ) where 28 | 29 | import UnliftIO.IO.File 30 | -------------------------------------------------------------------------------- /rio/src/RIO/FilePath.hs: -------------------------------------------------------------------------------- 1 | module RIO.FilePath 2 | ( module System.FilePath 3 | , getSearchPath 4 | ) where 5 | 6 | import Control.Monad.IO.Class 7 | import System.FilePath hiding(getSearchPath) 8 | import qualified System.FilePath 9 | 10 | -- | Lifted version of 'System.FilePath.getSearchPath' 11 | getSearchPath :: MonadIO m => m [FilePath] 12 | getSearchPath = liftIO System.FilePath.getSearchPath 13 | -------------------------------------------------------------------------------- /rio/src/RIO/HashMap.hs: -------------------------------------------------------------------------------- 1 | -- | Strict @Map@ with hashed keys. Import as: 2 | -- 3 | -- > import qualified RIO.HashMap as HM 4 | -- 5 | -- This module does not export any partial functions. For those, see 6 | -- "RIO.HashMap.Partial" 7 | module RIO.HashMap 8 | ( 9 | Data.HashMap.Strict.HashMap 10 | 11 | -- * Construction 12 | , Data.HashMap.Strict.empty 13 | , Data.HashMap.Strict.singleton 14 | 15 | -- * Basic interface 16 | , Data.HashMap.Strict.null 17 | , Data.HashMap.Strict.size 18 | , Data.HashMap.Strict.member 19 | , Data.HashMap.Strict.lookup 20 | , Data.HashMap.Strict.lookupDefault 21 | , Data.HashMap.Strict.insert 22 | , Data.HashMap.Strict.insertWith 23 | , Data.HashMap.Strict.delete 24 | , Data.HashMap.Strict.adjust 25 | , Data.HashMap.Strict.update 26 | , Data.HashMap.Strict.alter 27 | 28 | -- * Combine 29 | -- ** Union 30 | , Data.HashMap.Strict.union 31 | , Data.HashMap.Strict.unionWith 32 | , Data.HashMap.Strict.unionWithKey 33 | , Data.HashMap.Strict.unions 34 | 35 | -- * Transformations 36 | , Data.HashMap.Strict.map 37 | , Data.HashMap.Strict.mapWithKey 38 | , Data.HashMap.Strict.traverseWithKey 39 | 40 | -- * Difference and intersection 41 | , Data.HashMap.Strict.difference 42 | , Data.HashMap.Strict.differenceWith 43 | , Data.HashMap.Strict.intersection 44 | , Data.HashMap.Strict.intersectionWith 45 | , Data.HashMap.Strict.intersectionWithKey 46 | 47 | -- * Folds 48 | , Data.HashMap.Strict.foldl' 49 | , Data.HashMap.Strict.foldlWithKey' 50 | , Data.HashMap.Strict.foldr 51 | , Data.HashMap.Strict.foldrWithKey 52 | 53 | -- * Filter 54 | , Data.HashMap.Strict.filter 55 | , Data.HashMap.Strict.filterWithKey 56 | , Data.HashMap.Strict.mapMaybe 57 | , Data.HashMap.Strict.mapMaybeWithKey 58 | 59 | -- * Conversions 60 | , Data.HashMap.Strict.keys 61 | , Data.HashMap.Strict.elems 62 | 63 | -- ** Lists 64 | , Data.HashMap.Strict.toList 65 | , Data.HashMap.Strict.fromList 66 | , Data.HashMap.Strict.fromListWith 67 | ) where 68 | 69 | import Data.HashMap.Strict 70 | -------------------------------------------------------------------------------- /rio/src/RIO/HashMap/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Strict @HashMap@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.HashMap.Partial as HM' 4 | module RIO.HashMap.Partial 5 | ( 6 | -- * Basic interface 7 | (Data.HashMap.Strict.!) 8 | ) where 9 | 10 | import qualified Data.HashMap.Strict 11 | -------------------------------------------------------------------------------- /rio/src/RIO/HashSet.hs: -------------------------------------------------------------------------------- 1 | -- | @Set@ with hashed members. Import as: 2 | -- 3 | -- > import qualified RIO.HashSet as HS 4 | module RIO.HashSet 5 | ( 6 | Data.HashSet.HashSet 7 | 8 | -- * Construction 9 | , Data.HashSet.empty 10 | , Data.HashSet.singleton 11 | 12 | -- * Combine 13 | , Data.HashSet.union 14 | , Data.HashSet.unions 15 | 16 | -- * Basic interface 17 | , Data.HashSet.null 18 | , Data.HashSet.size 19 | , Data.HashSet.member 20 | , Data.HashSet.insert 21 | , Data.HashSet.delete 22 | 23 | -- * Transformations 24 | , Data.HashSet.map 25 | 26 | -- * Difference and intersection 27 | , Data.HashSet.difference 28 | , Data.HashSet.intersection 29 | 30 | -- * Folds 31 | , Data.HashSet.foldl' 32 | , Data.HashSet.foldr 33 | 34 | -- * Filter 35 | , Data.HashSet.filter 36 | 37 | -- * Conversions 38 | 39 | -- ** Lists 40 | , Data.HashSet.toList 41 | , Data.HashSet.fromList 42 | 43 | -- * HashMaps 44 | , Data.HashSet.toMap 45 | , Data.HashSet.fromMap 46 | ) where 47 | 48 | import qualified Data.HashSet 49 | -------------------------------------------------------------------------------- /rio/src/RIO/Lens.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- Module : RIO.Lens 3 | -- License : MIT 4 | -- Maintainer: Colin Woodbury 5 | -- 6 | -- Extra utilities from @microlens@. 7 | -- 8 | -- @since: 0.1.16.0 9 | module RIO.Lens 10 | ( -- * Fold 11 | SimpleFold 12 | , toListOf 13 | , has 14 | -- * Lens 15 | , _1, _2, _3, _4, _5 16 | , at 17 | , lens 18 | -- * Iso 19 | , non 20 | -- * Traversal 21 | , singular 22 | , failing 23 | , filtered 24 | , both 25 | , traversed 26 | , each 27 | , ix 28 | , _head 29 | , _tail 30 | , _init 31 | , _last 32 | -- * Prism 33 | , _Left 34 | , _Right 35 | , _Just 36 | , _Nothing 37 | ) where 38 | 39 | import Lens.Micro 40 | -------------------------------------------------------------------------------- /rio/src/RIO/List.hs: -------------------------------------------------------------------------------- 1 | -- | @List@. Import as: 2 | -- 3 | -- > import qualified RIO.List as L 4 | -- 5 | -- This module does not export any partial functions. For those, see 6 | -- "RIO.List.Partial" 7 | module RIO.List 8 | ( 9 | -- * Basic functions 10 | (Data.List.++) 11 | , Data.List.uncons 12 | , Data.List.null 13 | , Data.List.length 14 | , headMaybe 15 | , lastMaybe 16 | , tailMaybe 17 | , initMaybe 18 | 19 | -- * List transformations 20 | , Data.List.map 21 | , Data.List.reverse 22 | 23 | , Data.List.intersperse 24 | , Data.List.intercalate 25 | , Data.List.transpose 26 | 27 | , Data.List.subsequences 28 | , Data.List.permutations 29 | 30 | -- * Reducing lists (folds) 31 | 32 | , Data.List.foldl 33 | , Data.List.foldl' 34 | , Data.List.foldr 35 | 36 | -- ** Special folds 37 | 38 | , Data.List.concat 39 | , Data.List.concatMap 40 | , Data.List.and 41 | , Data.List.or 42 | , Data.List.any 43 | , Data.List.all 44 | , Data.List.sum 45 | , Data.List.product 46 | , maximumMaybe 47 | , minimumMaybe 48 | , maximumByMaybe 49 | , minimumByMaybe 50 | 51 | -- * Building lists 52 | 53 | -- ** Scans 54 | , Data.List.scanl 55 | , Data.List.scanl' 56 | , Data.List.scanr 57 | , Data.List.scanl1 58 | , Data.List.scanr1 59 | 60 | -- ** Accumulating maps 61 | , Data.List.mapAccumL 62 | , Data.List.mapAccumR 63 | 64 | -- ** Infinite lists 65 | , Data.List.iterate 66 | , Data.List.repeat 67 | , Data.List.replicate 68 | , Data.List.cycle 69 | 70 | -- ** Unfolding 71 | , Data.List.unfoldr 72 | 73 | -- * Sublists 74 | 75 | -- ** Extracting sublists 76 | , Data.List.take 77 | , Data.List.drop 78 | , Data.List.splitAt 79 | 80 | , Data.List.takeWhile 81 | , Data.List.dropWhile 82 | , Data.List.dropWhileEnd 83 | , Data.List.span 84 | , Data.List.break 85 | 86 | , Data.List.stripPrefix 87 | , stripSuffix 88 | , dropPrefix 89 | , dropSuffix 90 | 91 | , Data.List.group 92 | 93 | , Data.List.inits 94 | , Data.List.tails 95 | 96 | -- ** Predicates 97 | , Data.List.isPrefixOf 98 | , Data.List.isSuffixOf 99 | , Data.List.isInfixOf 100 | , Data.List.isSubsequenceOf 101 | 102 | -- * Searching lists 103 | 104 | -- ** Searching by equality 105 | , Data.List.elem 106 | , Data.List.notElem 107 | , Data.List.lookup 108 | 109 | -- ** Searching with a predicate 110 | , Data.List.find 111 | , Data.List.filter 112 | , Data.List.partition 113 | 114 | -- * Indexing lists 115 | -- | These functions treat a list @xs@ as a indexed collection, 116 | -- with indices ranging from 0 to @'length' xs - 1@. 117 | 118 | , Data.List.elemIndex 119 | , Data.List.elemIndices 120 | 121 | , Data.List.findIndex 122 | , Data.List.findIndices 123 | 124 | -- * Zipping and unzipping lists 125 | 126 | , Data.List.zip 127 | , Data.List.zip3 128 | , Data.List.zip4 129 | , Data.List.zip5 130 | , Data.List.zip6 131 | , Data.List.zip7 132 | 133 | , Data.List.zipWith 134 | , Data.List.zipWith3 135 | , Data.List.zipWith4 136 | , Data.List.zipWith5 137 | , Data.List.zipWith6 138 | , Data.List.zipWith7 139 | 140 | , Data.List.unzip 141 | , Data.List.unzip3 142 | , Data.List.unzip4 143 | , Data.List.unzip5 144 | , Data.List.unzip6 145 | , Data.List.unzip7 146 | 147 | -- * Special lists 148 | 149 | -- ** Functions on strings 150 | , Data.List.lines 151 | , linesCR 152 | , Data.List.words 153 | , Data.List.unlines 154 | , Data.List.unwords 155 | 156 | -- ** \"Set\" operations 157 | 158 | , Data.List.nub 159 | 160 | , Data.List.delete 161 | , (Data.List.\\) 162 | 163 | , Data.List.union 164 | , Data.List.intersect 165 | 166 | -- ** Ordered lists 167 | , Data.List.sort 168 | , Data.List.sortOn 169 | , Data.List.insert 170 | 171 | -- * Generalized functions 172 | 173 | -- ** The \"@By@\" operations 174 | -- | By convention, overloaded functions have a non-overloaded 175 | -- counterpart whose name is suffixed with \`@By@\'. 176 | -- 177 | -- It is often convenient to use these functions together with 178 | -- 'Data.Function.on', for instance @'sortBy' ('compare' 179 | -- \`on\` 'fst')@. 180 | 181 | -- *** User-supplied equality (replacing an @Eq@ context) 182 | -- | The predicate is assumed to define an equivalence. 183 | , Data.List.nubBy 184 | , Data.List.deleteBy 185 | , Data.List.deleteFirstsBy 186 | , Data.List.unionBy 187 | , Data.List.intersectBy 188 | , Data.List.groupBy 189 | 190 | -- *** User-supplied comparison (replacing an @Ord@ context) 191 | -- | The function is assumed to define a total ordering. 192 | , Data.List.sortBy 193 | , Data.List.insertBy 194 | 195 | -- ** The \"@generic@\" operations 196 | -- | The prefix \`@generic@\' indicates an overloaded function that 197 | -- is a generalized version of a "Prelude" function. 198 | 199 | , Data.List.genericLength 200 | , Data.List.genericTake 201 | , Data.List.genericDrop 202 | , Data.List.genericSplitAt 203 | , Data.List.genericIndex 204 | , Data.List.genericReplicate 205 | 206 | ) where 207 | 208 | import qualified Data.List 209 | 210 | import Data.List(stripPrefix) 211 | import Data.Maybe (fromMaybe) 212 | 213 | -- | Remove the suffix from the given list, if present 214 | -- 215 | -- @since 0.0.0 216 | stripSuffix :: Eq a 217 | => [a] -- ^ suffix 218 | -> [a] 219 | -> Maybe [a] 220 | stripSuffix suffix list = 221 | fmap reverse (stripPrefix (reverse suffix) (reverse list)) 222 | 223 | -- | Drop prefix if present, otherwise return original list. 224 | -- 225 | -- @since 0.0.0.0 226 | dropPrefix :: Eq a 227 | => [a] -- ^ prefix 228 | -> [a] 229 | -> [a] 230 | dropPrefix prefix t = fromMaybe t (stripPrefix prefix t) 231 | 232 | -- | Drop prefix if present, otherwise return original list. 233 | -- 234 | -- @since 0.0.0.0 235 | dropSuffix :: Eq a 236 | => [a] -- ^ suffix 237 | -> [a] 238 | -> [a] 239 | dropSuffix suffix t = fromMaybe t (stripSuffix suffix t) 240 | 241 | -- | 'linesCR' breaks a 'String' up into a list of `String`s at newline 242 | -- 'Char's. It is very similar to 'lines', but it also removes any 243 | -- trailing @'\r'@ 'Char's. The resulting 'String' values do not contain 244 | -- newlines or trailing @'\r'@ characters. 245 | -- 246 | -- @since 0.1.0.0 247 | linesCR :: String -> [String] 248 | linesCR = map (dropSuffix "\r") . lines 249 | 250 | safeListCall :: Foldable t => (t a -> b) -> t a -> Maybe b 251 | safeListCall f xs 252 | | Data.List.null xs = Nothing 253 | | otherwise = Just $ f xs 254 | 255 | -- | @since 0.1.3.0 256 | headMaybe :: [a] -> Maybe a 257 | headMaybe = safeListCall Data.List.head 258 | 259 | -- | @since 0.1.3.0 260 | lastMaybe :: [a] -> Maybe a 261 | lastMaybe = safeListCall Data.List.last 262 | 263 | -- | @since 0.1.3.0 264 | tailMaybe :: [a] -> Maybe [a] 265 | tailMaybe = safeListCall Data.List.tail 266 | 267 | -- | @since 0.1.3.0 268 | initMaybe :: [a] -> Maybe [a] 269 | initMaybe = safeListCall Data.List.init 270 | 271 | -- | @since 0.1.3.0 272 | maximumMaybe :: (Ord a, Foldable t) => t a -> Maybe a 273 | maximumMaybe = safeListCall Data.List.maximum 274 | 275 | -- | @since 0.1.3.0 276 | minimumMaybe :: (Ord a, Foldable t) => t a -> Maybe a 277 | minimumMaybe = safeListCall Data.List.minimum 278 | 279 | -- | @since 0.1.3.0 280 | maximumByMaybe :: (Foldable t) => (a -> a -> Ordering) -> t a -> Maybe a 281 | maximumByMaybe f = safeListCall (Data.List.maximumBy f) 282 | 283 | -- | @since 0.1.3.0 284 | minimumByMaybe :: (Foldable t) => (a -> a -> Ordering) -> t a -> Maybe a 285 | minimumByMaybe f = safeListCall (Data.List.minimumBy f) 286 | -------------------------------------------------------------------------------- /rio/src/RIO/List/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | @List@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.List.Partial as L' 4 | module RIO.List.Partial 5 | ( 6 | -- * Basic functions 7 | Data.List.head 8 | , Data.List.last 9 | , Data.List.tail 10 | , Data.List.init 11 | 12 | -- * Reducing lists (folds) 13 | , Data.List.foldl1 14 | , Data.List.foldl1' 15 | , Data.List.foldr1 16 | 17 | -- ** Special folds 18 | , Data.List.maximum 19 | , Data.List.minimum 20 | , Data.List.maximumBy 21 | , Data.List.minimumBy 22 | 23 | -- * Building lists 24 | 25 | -- ** Scans 26 | -- 27 | -- These functions are not partial, they are being exported here for legacy 28 | -- reasons, they may be removed from this module on a future major release 29 | , Data.List.scanl1 30 | , Data.List.scanr1 31 | 32 | -- * Indexing lists 33 | , (Data.List.!!) 34 | ) where 35 | 36 | import qualified Data.List 37 | -------------------------------------------------------------------------------- /rio/src/RIO/Map.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | 3 | -- | Strict @Map@. Import as: 4 | -- 5 | -- > import qualified RIO.Map as Map 6 | -- 7 | -- This module does not export any partial or unchecked functions. For those, 8 | -- see "RIO.Map.Partial" and "RIO.Map.Unchecked" 9 | module RIO.Map 10 | ( 11 | -- * Map type 12 | Data.Map.Strict.Map 13 | 14 | -- * Operators 15 | #if MIN_VERSION_containers(0,5,9) 16 | , (Data.Map.Strict.!?) 17 | #endif 18 | , (Data.Map.Strict.\\) 19 | 20 | -- * Query 21 | , Data.Map.Strict.null 22 | , Data.Map.Strict.size 23 | , Data.Map.Strict.member 24 | , Data.Map.Strict.notMember 25 | , Data.Map.Strict.lookup 26 | , Data.Map.Strict.findWithDefault 27 | , Data.Map.Strict.lookupLT 28 | , Data.Map.Strict.lookupGT 29 | , Data.Map.Strict.lookupLE 30 | , Data.Map.Strict.lookupGE 31 | 32 | -- * Construction 33 | , Data.Map.Strict.empty 34 | , Data.Map.Strict.singleton 35 | 36 | -- ** Insertion 37 | , Data.Map.Strict.insert 38 | , Data.Map.Strict.insertWith 39 | , Data.Map.Strict.insertWithKey 40 | , Data.Map.Strict.insertLookupWithKey 41 | 42 | -- ** Delete\/Update 43 | , Data.Map.Strict.delete 44 | , Data.Map.Strict.adjust 45 | , Data.Map.Strict.adjustWithKey 46 | , Data.Map.Strict.update 47 | , Data.Map.Strict.updateWithKey 48 | , Data.Map.Strict.updateLookupWithKey 49 | , Data.Map.Strict.alter 50 | #if MIN_VERSION_containers(0,5,8) 51 | , Data.Map.Strict.alterF 52 | #endif 53 | 54 | -- * Combine 55 | 56 | -- ** Union 57 | , Data.Map.Strict.union 58 | , Data.Map.Strict.unionWith 59 | , Data.Map.Strict.unionWithKey 60 | , Data.Map.Strict.unions 61 | , Data.Map.Strict.unionsWith 62 | 63 | -- ** Difference 64 | , Data.Map.Strict.difference 65 | , Data.Map.Strict.differenceWith 66 | , Data.Map.Strict.differenceWithKey 67 | 68 | -- ** Intersection 69 | , Data.Map.Strict.intersection 70 | , Data.Map.Strict.intersectionWith 71 | , Data.Map.Strict.intersectionWithKey 72 | 73 | -- ** General combining functions 74 | -- | See "Data.Map.Merge.Strict" 75 | 76 | -- ** Deprecated general combining function 77 | 78 | , Data.Map.Strict.mergeWithKey 79 | 80 | -- * Traversal 81 | -- ** Map 82 | , Data.Map.Strict.map 83 | , Data.Map.Strict.mapWithKey 84 | , Data.Map.Strict.traverseWithKey 85 | #if MIN_VERSION_containers(0,5,8) 86 | , Data.Map.Strict.traverseMaybeWithKey 87 | #endif 88 | , Data.Map.Strict.mapAccum 89 | , Data.Map.Strict.mapAccumWithKey 90 | , Data.Map.Strict.mapAccumRWithKey 91 | , Data.Map.Strict.mapKeys 92 | , Data.Map.Strict.mapKeysWith 93 | 94 | -- * Folds 95 | , Data.Map.Strict.foldr 96 | , Data.Map.Strict.foldl 97 | , Data.Map.Strict.foldrWithKey 98 | , Data.Map.Strict.foldlWithKey 99 | , Data.Map.Strict.foldMapWithKey 100 | 101 | -- ** Strict folds 102 | , Data.Map.Strict.foldr' 103 | , Data.Map.Strict.foldl' 104 | , Data.Map.Strict.foldrWithKey' 105 | , Data.Map.Strict.foldlWithKey' 106 | 107 | -- * Conversion 108 | , Data.Map.Strict.elems 109 | , Data.Map.Strict.keys 110 | , Data.Map.Strict.assocs 111 | , Data.Map.Strict.keysSet 112 | , Data.Map.Strict.fromSet 113 | 114 | -- ** Lists 115 | , Data.Map.Strict.toList 116 | , Data.Map.Strict.fromList 117 | , Data.Map.Strict.fromListWith 118 | , Data.Map.Strict.fromListWithKey 119 | 120 | -- ** Ordered lists 121 | , Data.Map.Strict.toAscList 122 | #if MIN_VERSION_containers(0,5,8) 123 | , Data.Map.Strict.toDescList 124 | #endif 125 | 126 | -- * Filter 127 | , Data.Map.Strict.filter 128 | , Data.Map.Strict.filterWithKey 129 | #if MIN_VERSION_containers(0,5,8) 130 | , Data.Map.Strict.restrictKeys 131 | , Data.Map.Strict.withoutKeys 132 | #endif 133 | , Data.Map.Strict.partition 134 | , Data.Map.Strict.partitionWithKey 135 | 136 | #if MIN_VERSION_containers(0,5,8) 137 | , Data.Map.Strict.takeWhileAntitone 138 | , Data.Map.Strict.dropWhileAntitone 139 | , Data.Map.Strict.spanAntitone 140 | #endif 141 | 142 | , Data.Map.Strict.mapMaybe 143 | , Data.Map.Strict.mapMaybeWithKey 144 | , Data.Map.Strict.mapEither 145 | , Data.Map.Strict.mapEitherWithKey 146 | 147 | , Data.Map.Strict.split 148 | , Data.Map.Strict.splitLookup 149 | , Data.Map.Strict.splitRoot 150 | 151 | -- * Submap 152 | , Data.Map.Strict.isSubmapOf 153 | , Data.Map.Strict.isSubmapOfBy 154 | , Data.Map.Strict.isProperSubmapOf 155 | , Data.Map.Strict.isProperSubmapOfBy 156 | 157 | -- * Indexed 158 | , Data.Map.Strict.lookupIndex 159 | , Data.Map.Strict.elemAt 160 | , Data.Map.Strict.deleteAt 161 | #if MIN_VERSION_containers(0,5,8) 162 | , Data.Map.Strict.take 163 | , Data.Map.Strict.drop 164 | , Data.Map.Strict.splitAt 165 | #endif 166 | 167 | -- * Min\/Max 168 | #if MIN_VERSION_containers(0,5,9) 169 | , Data.Map.Strict.lookupMin 170 | , Data.Map.Strict.lookupMax 171 | #endif 172 | , Data.Map.Strict.deleteMin 173 | , Data.Map.Strict.deleteMax 174 | , Data.Map.Strict.updateMin 175 | , Data.Map.Strict.updateMax 176 | , Data.Map.Strict.updateMinWithKey 177 | , Data.Map.Strict.updateMaxWithKey 178 | , Data.Map.Strict.minView 179 | , Data.Map.Strict.maxView 180 | , Data.Map.Strict.minViewWithKey 181 | , Data.Map.Strict.maxViewWithKey 182 | 183 | -- * Debugging 184 | , Data.Map.Strict.showTree 185 | , Data.Map.Strict.showTreeWith 186 | , Data.Map.Strict.valid 187 | ) where 188 | 189 | import qualified Data.Map.Strict 190 | -------------------------------------------------------------------------------- /rio/src/RIO/Map/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Strict @Map@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Map.Partial as Map' 4 | module RIO.Map.Partial 5 | ( 6 | -- * Operators 7 | (Data.Map.Strict.!) 8 | -- * Indexed 9 | , Data.Map.Strict.elemAt 10 | , Data.Map.Strict.deleteAt 11 | , Data.Map.Strict.findIndex 12 | , Data.Map.Strict.updateAt 13 | 14 | -- * Min\/Max 15 | , Data.Map.Strict.findMin 16 | , Data.Map.Strict.findMax 17 | , Data.Map.Strict.deleteFindMin 18 | , Data.Map.Strict.deleteFindMax 19 | ) where 20 | 21 | import qualified Data.Map.Strict 22 | -------------------------------------------------------------------------------- /rio/src/RIO/Map/Unchecked.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | 3 | -- | This module contains functions from "Data.Map.Strict" that have unchecked 4 | -- preconditions on their input. If these preconditions are not satisfied, 5 | -- the data structure may end up in an invalid state and other operations 6 | -- may misbehave. Import as: 7 | -- 8 | -- > import qualified RIO.Map.Unchecked as Map' 9 | module RIO.Map.Unchecked 10 | ( 11 | -- * Traversal 12 | -- ** Map 13 | Data.Map.Strict.mapKeysMonotonic 14 | 15 | -- * Conversion 16 | -- ** Ordered lists 17 | , Data.Map.Strict.toAscList -- FIXME: remove in the next major version (0.2.0.0) 18 | , Data.Map.Strict.fromAscList 19 | , Data.Map.Strict.fromAscListWith 20 | , Data.Map.Strict.fromAscListWithKey 21 | , Data.Map.Strict.fromDistinctAscList 22 | #if MIN_VERSION_containers(0,5,8) 23 | , Data.Map.Strict.toDescList -- FIXME: remove in the next major version (0.2.0.0) 24 | , Data.Map.Strict.fromDescList 25 | , Data.Map.Strict.fromDescListWith 26 | , Data.Map.Strict.fromDescListWithKey 27 | , Data.Map.Strict.fromDistinctDescList 28 | #endif 29 | 30 | ) where 31 | 32 | import qualified Data.Map.Strict 33 | -------------------------------------------------------------------------------- /rio/src/RIO/NonEmpty.hs: -------------------------------------------------------------------------------- 1 | -- | @NonEmpty@ list. Import as: 2 | -- 3 | -- > import qualified RIO.NonEmpty as NE 4 | -- 5 | -- This module does not export any partial functions. For those, see 6 | -- "RIO.NonEmpty.Partial" 7 | module RIO.NonEmpty 8 | ( 9 | -- * The type of non-empty streams 10 | Data.List.NonEmpty.NonEmpty(..) 11 | 12 | -- * Non-empty stream transformations 13 | , Data.List.NonEmpty.map 14 | , Data.List.NonEmpty.intersperse 15 | , Data.List.NonEmpty.scanl 16 | , Data.List.NonEmpty.scanr 17 | , Data.List.NonEmpty.scanl1 18 | , Data.List.NonEmpty.scanr1 19 | , Data.List.NonEmpty.transpose 20 | , Data.List.NonEmpty.sortBy 21 | , Data.List.NonEmpty.sortWith 22 | 23 | -- * Basic functions 24 | , Data.List.NonEmpty.length 25 | , Data.List.NonEmpty.head 26 | , Data.List.NonEmpty.tail 27 | , Data.List.NonEmpty.last 28 | , Data.List.NonEmpty.init 29 | , (Data.List.NonEmpty.<|) 30 | , Data.List.NonEmpty.cons 31 | , Data.List.NonEmpty.uncons 32 | , Data.List.NonEmpty.unfoldr 33 | , Data.List.NonEmpty.sort 34 | , Data.List.NonEmpty.reverse 35 | , Data.List.NonEmpty.inits 36 | , Data.List.NonEmpty.tails 37 | 38 | -- * Building streams 39 | , Data.List.NonEmpty.iterate 40 | , Data.List.NonEmpty.repeat 41 | , Data.List.NonEmpty.cycle 42 | , Data.List.NonEmpty.insert 43 | , Data.List.NonEmpty.some1 44 | 45 | -- * Extracting sublists 46 | , Data.List.NonEmpty.take 47 | , Data.List.NonEmpty.drop 48 | , Data.List.NonEmpty.splitAt 49 | , Data.List.NonEmpty.takeWhile 50 | , Data.List.NonEmpty.dropWhile 51 | , Data.List.NonEmpty.span 52 | , Data.List.NonEmpty.break 53 | , Data.List.NonEmpty.filter 54 | , Data.List.NonEmpty.partition 55 | , Data.List.NonEmpty.group 56 | , Data.List.NonEmpty.groupBy 57 | , Data.List.NonEmpty.groupWith 58 | , Data.List.NonEmpty.groupAllWith 59 | , Data.List.NonEmpty.group1 60 | , Data.List.NonEmpty.groupBy1 61 | , Data.List.NonEmpty.groupWith1 62 | , Data.List.NonEmpty.groupAllWith1 63 | 64 | -- * Sublist predicates 65 | , Data.List.NonEmpty.isPrefixOf 66 | 67 | -- * Set-like operations 68 | , Data.List.NonEmpty.nub 69 | , Data.List.NonEmpty.nubBy 70 | 71 | -- * Zipping and unzipping streams 72 | , Data.List.NonEmpty.zip 73 | , Data.List.NonEmpty.zipWith 74 | , Data.List.NonEmpty.unzip 75 | 76 | -- * Converting to and from a list 77 | , Data.List.NonEmpty.nonEmpty 78 | , Data.List.NonEmpty.toList 79 | , Data.List.NonEmpty.xor 80 | 81 | ) where 82 | 83 | import qualified Data.List.NonEmpty 84 | -------------------------------------------------------------------------------- /rio/src/RIO/NonEmpty/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | @NonEmpty@ list partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.NonEmpty.Partial as NE' 4 | module RIO.NonEmpty.Partial 5 | ( 6 | -- * Indexing streams 7 | (Data.List.NonEmpty.!!) 8 | 9 | -- * Converting to and from a list 10 | , Data.List.NonEmpty.fromList 11 | 12 | ) where 13 | 14 | import qualified Data.List.NonEmpty 15 | -------------------------------------------------------------------------------- /rio/src/RIO/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Partial as RIO' 4 | module RIO.Partial 5 | ( Data.Maybe.fromJust 6 | , Prelude.read 7 | , Prelude.toEnum 8 | , Prelude.pred 9 | , Prelude.succ 10 | ) where 11 | 12 | import qualified Data.Maybe 13 | import qualified Prelude 14 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude.hs: -------------------------------------------------------------------------------- 1 | module RIO.Prelude 2 | ( 3 | module RIO.Prelude.Types 4 | -- * @Bool@ 5 | -- | Re-exported from "Data.Bool": 6 | , (Data.Bool.||) 7 | , (Data.Bool.&&) 8 | , Data.Bool.not 9 | , Data.Bool.otherwise 10 | , Data.Bool.bool 11 | 12 | -- * @Maybe@ 13 | -- | Re-exported from "Data.Maybe": 14 | , Data.Maybe.maybe 15 | , Data.Maybe.fromMaybe 16 | , RIO.Prelude.Extra.fromFirst 17 | , Data.Maybe.isJust 18 | , Data.Maybe.isNothing 19 | , Data.Maybe.listToMaybe 20 | , Data.Maybe.maybeToList 21 | , Data.Maybe.catMaybes 22 | , Data.Maybe.mapMaybe 23 | , RIO.Prelude.Extra.mapMaybeA 24 | , RIO.Prelude.Extra.mapMaybeM 25 | , RIO.Prelude.Extra.forMaybeA 26 | , RIO.Prelude.Extra.forMaybeM 27 | 28 | -- * @Either@ 29 | -- | Re-exported from "Data.Either": 30 | , Data.Either.either 31 | , Data.Either.fromLeft 32 | , Data.Either.fromRight 33 | , Data.Either.isLeft 34 | , Data.Either.isRight 35 | , RIO.Prelude.Extra.mapLeft 36 | , Data.Either.lefts 37 | , Data.Either.partitionEithers 38 | , Data.Either.rights 39 | 40 | -- * Tuples 41 | -- | Re-exported from "Data.Tuple": 42 | , Data.Tuple.fst 43 | , Data.Tuple.snd 44 | , Data.Tuple.curry 45 | , Data.Tuple.uncurry 46 | -- , Data.Tuple.swap -- TODO: export? 47 | 48 | -- * @Eq@ 49 | -- | Re-exported from "Data.Eq": 50 | , (Data.Eq.==) 51 | , (Data.Eq./=) 52 | 53 | -- * @Ord@ 54 | -- | Re-exported from "Data.Ord": 55 | , (Data.Ord.<) 56 | , (Data.Ord.<=) 57 | , (Data.Ord.>) 58 | , (Data.Ord.>=) 59 | , Data.Ord.max 60 | , Data.Ord.min 61 | , Data.Ord.compare 62 | , Data.Ord.comparing 63 | , Data.Ord.Down(..) 64 | 65 | -- * @Enum@ 66 | -- | Re-exported from "Prelude": 67 | , Prelude.fromEnum 68 | 69 | -- * @Bounded@ 70 | -- | Re-exported from "Prelude": 71 | , Prelude.minBound 72 | , Prelude.maxBound 73 | 74 | -- * @Num@ 75 | -- | Re-exported from "Prelude": 76 | , (Prelude.+) 77 | , (Prelude.-) 78 | , (*) -- HSE can't parse qualified export, which results in hlint error. 79 | , (Prelude.^) 80 | , Prelude.negate 81 | , Prelude.abs 82 | , Prelude.signum 83 | , Prelude.fromInteger 84 | , Prelude.subtract 85 | 86 | -- * @Real@ 87 | -- | Re-exported from "Prelude": 88 | , Prelude.toRational 89 | 90 | -- * @Integral@ 91 | -- | Re-exported from "Prelude": 92 | , Prelude.quot 93 | , Prelude.rem 94 | , Prelude.div 95 | , Prelude.mod 96 | , Prelude.quotRem 97 | , Prelude.divMod 98 | , Prelude.toInteger 99 | , Prelude.even 100 | , Prelude.odd 101 | , Prelude.gcd 102 | , Prelude.lcm 103 | , Prelude.fromIntegral 104 | 105 | -- * @Fractional@ 106 | -- | Re-exported from "Prelude": 107 | , (Prelude./) 108 | , (Prelude.^^) 109 | , Prelude.recip 110 | , Prelude.fromRational 111 | , Prelude.realToFrac 112 | 113 | -- * @Floating@ 114 | -- | Re-exported from "Prelude": 115 | , Prelude.pi 116 | , Prelude.exp 117 | , Prelude.log 118 | , Prelude.sqrt 119 | , (Prelude.**) 120 | , Prelude.logBase 121 | , Prelude.sin 122 | , Prelude.cos 123 | , Prelude.tan 124 | , Prelude.asin 125 | , Prelude.acos 126 | , Prelude.atan 127 | , Prelude.sinh 128 | , Prelude.cosh 129 | , Prelude.tanh 130 | , Prelude.asinh 131 | , Prelude.acosh 132 | , Prelude.atanh 133 | 134 | -- * @RealFrac@ 135 | -- | Re-exported from "Prelude": 136 | , Prelude.properFraction 137 | , Prelude.truncate 138 | , Prelude.round 139 | , Prelude.ceiling 140 | , Prelude.floor 141 | 142 | -- * @RealFloat@ 143 | -- | Re-exported from "Prelude": 144 | , Prelude.floatRadix 145 | , Prelude.floatDigits 146 | , Prelude.floatRange 147 | , Prelude.decodeFloat 148 | , Prelude.encodeFloat 149 | , Prelude.exponent 150 | , Prelude.significand 151 | , Prelude.scaleFloat 152 | , Prelude.isNaN 153 | , Prelude.isInfinite 154 | , Prelude.isDenormalized 155 | , Prelude.isNegativeZero 156 | , Prelude.isIEEE 157 | , Prelude.atan2 158 | 159 | -- * @Word@ 160 | -- | Re-exported from "Data.Word": 161 | , Data.Word.byteSwap16 162 | , Data.Word.byteSwap32 163 | , Data.Word.byteSwap64 164 | 165 | -- * @Semigroup@ 166 | -- | Re-exported from "Data.Semigroup": 167 | , (Data.Semigroup.<>) 168 | , RIO.Prelude.Renames.sappend 169 | 170 | -- * @Monoid@ 171 | -- | Re-exported from "Data.Monoid": 172 | , Data.Monoid.mempty 173 | , Data.Monoid.mappend 174 | , Data.Monoid.mconcat 175 | 176 | -- * @Functor@ 177 | -- | Re-exported from "Data.Functor": 178 | , Data.Functor.fmap 179 | , (Data.Functor.<$>) 180 | , (Data.Functor.<$) 181 | , (Data.Functor.$>) 182 | , Data.Functor.void 183 | , (RIO.Prelude.Extra.<&>) 184 | 185 | -- * @Applicative@ 186 | -- | Re-exported from "Control.Applicative": 187 | , Control.Applicative.pure 188 | , (Control.Applicative.<*>) 189 | , (Control.Applicative.<*) 190 | , (Control.Applicative.*>) 191 | , Control.Applicative.liftA 192 | , Control.Applicative.liftA2 193 | , Control.Applicative.liftA3 194 | , Control.Monad.forever 195 | , Data.Foldable.traverse_ 196 | , Data.Foldable.for_ 197 | , Data.Foldable.sequenceA_ 198 | , Control.Monad.filterM 199 | , Control.Monad.replicateM_ 200 | , Control.Monad.zipWithM 201 | , Control.Monad.zipWithM_ 202 | 203 | -- * @Monad@ 204 | -- | Re-exported from "Control.Monad": 205 | , Control.Monad.return 206 | , Control.Monad.join 207 | , Control.Monad.fail 208 | , (Control.Monad.>>=) 209 | , (Control.Monad.>>) 210 | , (Control.Monad.=<<) 211 | , (Control.Monad.>=>) 212 | , (Control.Monad.<=<) 213 | , (Control.Monad.<$!>) 214 | , Control.Monad.liftM 215 | , Control.Monad.liftM2 216 | , RIO.Prelude.Extra.whenM 217 | , RIO.Prelude.Extra.unlessM 218 | , Data.Foldable.mapM_ 219 | , Data.Foldable.forM_ 220 | , Data.Foldable.sequence_ 221 | 222 | , Control.Monad.foldM 223 | , Control.Monad.foldM_ 224 | -- TODO: Export these as well perhaps? 225 | -- , Data.Foldable.foldlM 226 | -- , Data.Foldable.foldrM 227 | 228 | -- * @Foldable@ 229 | -- | Re-exported from "Data.Foldable": 230 | , Data.Foldable.foldr 231 | , Data.Foldable.foldl' 232 | , Data.Foldable.fold 233 | , Data.Foldable.foldMap 234 | , RIO.Prelude.Extra.foldMapM 235 | , Data.Foldable.elem 236 | , Data.Foldable.notElem 237 | , Data.Foldable.null 238 | , Data.Foldable.length 239 | , Data.Foldable.sum 240 | , Data.Foldable.product 241 | , Data.Foldable.all 242 | , Data.Foldable.any 243 | , Data.Foldable.and 244 | , Data.Foldable.or 245 | , Data.Foldable.toList 246 | , Data.Foldable.concat 247 | , Data.Foldable.concatMap 248 | 249 | -- * @Traversable@ 250 | -- | Re-exported from "Data.Traversable": 251 | , Data.Traversable.traverse 252 | , Data.Traversable.for 253 | , Data.Traversable.sequenceA 254 | , Data.Traversable.mapM 255 | , Data.Traversable.forM 256 | , Data.Traversable.sequence 257 | 258 | -- * @Alternative@ 259 | -- | Re-exported from "Control.Applicative": 260 | , (Control.Applicative.<|>) 261 | , Control.Applicative.some 262 | , Control.Applicative.many 263 | , Control.Applicative.optional 264 | , Data.Foldable.asum 265 | , Control.Monad.guard 266 | , Control.Monad.when 267 | , Control.Monad.unless 268 | 269 | -- * @Bifunctor@ 270 | -- | Re-exported from "Data.Bifunctor": 271 | , Data.Bifunctor.bimap 272 | , Data.Bifunctor.first 273 | , Data.Bifunctor.second 274 | 275 | -- * @Bifoldable@ 276 | -- | Re-exported from "Data.Bifoldable": 277 | , Data.Bifoldable.bifold 278 | , Data.Bifoldable.bifoldMap 279 | , Data.Bifoldable.bifoldr 280 | , Data.Bifoldable.bifoldl 281 | , Data.Bifoldable.bifoldr' 282 | , Data.Bifoldable.bifoldr1 283 | , Data.Bifoldable.bifoldrM 284 | , Data.Bifoldable.bifoldl' 285 | , Data.Bifoldable.bifoldl1 286 | , Data.Bifoldable.bifoldlM 287 | , Data.Bifoldable.bitraverse_ 288 | , Data.Bifoldable.bifor_ 289 | , Data.Bifoldable.bisequence_ 290 | , Data.Bifoldable.biasum 291 | , Data.Bifoldable.biList 292 | , Data.Bifoldable.binull 293 | , Data.Bifoldable.bilength 294 | , Data.Bifoldable.bielem 295 | , Data.Bifoldable.bimaximum 296 | , Data.Bifoldable.biminimum 297 | , Data.Bifoldable.bisum 298 | , Data.Bifoldable.biproduct 299 | , Data.Bifoldable.biconcat 300 | , Data.Bifoldable.biconcatMap 301 | , Data.Bifoldable.biand 302 | , Data.Bifoldable.bior 303 | , Data.Bifoldable.biany 304 | , Data.Bifoldable.biall 305 | , Data.Bifoldable.bimaximumBy 306 | , Data.Bifoldable.biminimumBy 307 | , Data.Bifoldable.binotElem 308 | , Data.Bifoldable.bifind 309 | 310 | -- * @Bitraverse@ 311 | -- | Re-exported from "Data.Bitraversable": 312 | , Data.Bitraversable.bitraverse 313 | , Data.Bitraversable.bisequence 314 | , Data.Bitraversable.bifor 315 | , Data.Bitraversable.bimapAccumL 316 | , Data.Bitraversable.bimapAccumR 317 | 318 | -- * @MonadPlus@ 319 | -- | Re-exported from "Control.Monad": 320 | , Control.Monad.mzero 321 | , Control.Monad.mplus 322 | , Control.Monad.msum 323 | , Control.Monad.mfilter 324 | 325 | -- * @Arrow@ 326 | -- | Re-exported from "Control.Arrow" and "Control.Category": 327 | , (Control.Arrow.&&&) 328 | , (Control.Arrow.***) 329 | , (Control.Category.>>>) 330 | 331 | -- * @Function@ 332 | -- | Re-exported from "Data.Function": 333 | , Data.Function.id 334 | , Data.Function.const 335 | , (Data.Function..) 336 | , (Data.Function.$) 337 | , (Data.Function.&) 338 | , Data.Function.flip 339 | , Data.Function.fix 340 | , Data.Function.on 341 | 342 | -- * Miscellaneous functions 343 | , (Prelude.$!) 344 | , Prelude.seq 345 | , Prelude.error 346 | , Prelude.undefined 347 | , Prelude.asTypeOf 348 | , RIO.Prelude.Extra.asIO 349 | 350 | -- * List 351 | -- | Re-exported from "Data.List": 352 | , (Data.List.++) 353 | , Data.List.break 354 | , Data.List.drop 355 | , Data.List.dropWhile 356 | , Data.List.filter 357 | , Data.List.lookup 358 | , Data.List.map 359 | , Data.List.replicate 360 | , Data.List.reverse 361 | , Data.List.span 362 | , Data.List.take 363 | , Data.List.takeWhile 364 | , Data.List.zip 365 | , Data.List.zipWith 366 | , RIO.Prelude.Extra.nubOrd 367 | 368 | 369 | -- * @String@ 370 | -- | Re-exported from "Data.String": 371 | , Data.String.fromString 372 | , Data.String.lines 373 | , Data.String.unlines 374 | , Data.String.unwords 375 | , Data.String.words 376 | 377 | -- ** @Show@ 378 | -- | Re-exported from "Text.Show": 379 | , Text.Show.show 380 | -- ** @Read@ 381 | -- | Re-exported from "Text.Read": 382 | , Text.Read.readMaybe 383 | 384 | -- * @NFData@ 385 | 386 | -- | Re-exported from "Control.DeepSeq": 387 | , (Control.DeepSeq.$!!) 388 | , Control.DeepSeq.rnf 389 | , Control.DeepSeq.deepseq 390 | , Control.DeepSeq.force 391 | 392 | -- * @Void@ 393 | -- | Re-exported from "Data.Void": 394 | , Data.Void.absurd 395 | 396 | -- * @Reader@ 397 | -- | Re-exported from "Control.Monad.Reader": 398 | , Control.Monad.Reader.lift 399 | , Control.Monad.Reader.ask 400 | , Control.Monad.Reader.asks 401 | , Control.Monad.Reader.local 402 | , Control.Monad.Reader.runReader 403 | , Control.Monad.Reader.runReaderT 404 | 405 | -- * @ByteString@ 406 | -- | Helper synonyms for converting bewteen lazy and strict @ByteString@s 407 | , RIO.Prelude.Renames.toStrictBytes 408 | , RIO.Prelude.Renames.fromStrictBytes 409 | 410 | -- * @ShortByteString@ 411 | -- | Re-exported from "Data.ByteString.Short": 412 | , Data.ByteString.Short.toShort 413 | , Data.ByteString.Short.fromShort 414 | 415 | -- * @Text@ 416 | , RIO.Prelude.Text.tshow 417 | , RIO.Prelude.Text.decodeUtf8Lenient 418 | -- | Re-exported from "Data.Text.Encoding": 419 | , Data.Text.Encoding.decodeUtf8' 420 | , Data.Text.Encoding.decodeUtf8With 421 | , Data.Text.Encoding.encodeUtf8 422 | , Data.Text.Encoding.encodeUtf8Builder 423 | , Data.Text.Encoding.Error.lenientDecode 424 | 425 | -- * @PrimMonad@ 426 | -- | Re-exported from "Control.Monad.Primitive": 427 | , Control.Monad.Primitive.primitive 428 | -- | Re-exported from "Control.Monad.ST": 429 | , Control.Monad.ST.runST 430 | ) where 431 | 432 | import qualified RIO.Prelude.Extra 433 | import qualified RIO.Prelude.Renames 434 | import qualified RIO.Prelude.Text 435 | import qualified RIO.Prelude.Types 436 | 437 | import qualified Control.Applicative 438 | import qualified Control.Arrow 439 | import qualified Control.Category 440 | import qualified Control.DeepSeq 441 | import qualified Control.Monad 442 | import qualified Control.Monad.Primitive (primitive) 443 | import qualified Control.Monad.Reader 444 | import qualified Control.Monad.ST 445 | import qualified Data.Bifoldable 446 | import qualified Data.Bifunctor 447 | import qualified Data.Bitraversable 448 | import qualified Data.Bool 449 | import qualified Data.ByteString.Short 450 | import qualified Data.Either 451 | import qualified Data.Eq 452 | import qualified Data.Foldable 453 | import qualified Data.Function 454 | import qualified Data.Functor 455 | import qualified Data.List 456 | import qualified Data.Maybe 457 | import qualified Data.Monoid 458 | import qualified Data.Ord 459 | import qualified Data.Semigroup 460 | import qualified Data.String 461 | import qualified Data.Text.Encoding 462 | (decodeUtf8', decodeUtf8With, encodeUtf8, encodeUtf8Builder) 463 | import qualified Data.Text.Encoding.Error (lenientDecode) 464 | import qualified Data.Traversable 465 | import qualified Data.Tuple 466 | import qualified Data.Void 467 | import qualified Data.Word 468 | import Prelude ((*)) 469 | import qualified Prelude 470 | import qualified Text.Read 471 | import qualified Text.Show 472 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Display.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 2 | module RIO.Prelude.Display 3 | ( Utf8Builder (..) 4 | , Display (..) 5 | , displayShow 6 | , utf8BuilderToText 7 | , utf8BuilderToLazyText 8 | , displayBytesUtf8 9 | , writeFileUtf8Builder 10 | ) where 11 | 12 | import Data.String (IsString (..)) 13 | import Data.ByteString (ByteString) 14 | import qualified Data.ByteString.Lazy as BL 15 | import qualified Data.ByteString.Builder as BB 16 | import Data.ByteString.Builder (Builder) 17 | import Data.Semigroup (Semigroup(..)) 18 | import Data.Text (Text) 19 | import qualified Data.Text.Lazy as TL 20 | import qualified Data.Text.Lazy.Encoding as TL 21 | import UnliftIO 22 | import Data.Text.Encoding (decodeUtf8With, encodeUtf8Builder) 23 | import Data.Text.Encoding.Error (lenientDecode) 24 | import Data.Int 25 | import Data.Word 26 | import System.Process.Typed (ProcessConfig, setEnvInherit) 27 | 28 | -- | A builder of binary data, with the invariant that the underlying 29 | -- data is supposed to be UTF-8 encoded. 30 | -- 31 | -- @since 0.1.0.0 32 | newtype Utf8Builder = Utf8Builder { getUtf8Builder :: Builder } 33 | deriving (Semigroup) 34 | 35 | -- Custom instance is created instead of deriving, otherwise list fusion breaks 36 | -- for `mconcat`. 37 | instance Monoid Utf8Builder where 38 | mempty = Utf8Builder mempty 39 | {-# INLINE mempty #-} 40 | mappend = (Data.Semigroup.<>) 41 | {-# INLINE mappend #-} 42 | mconcat = foldr mappend mempty 43 | {-# INLINE mconcat #-} 44 | 45 | -- | @since 0.1.0.0 46 | instance IsString Utf8Builder where 47 | fromString = Utf8Builder . BB.stringUtf8 48 | 49 | -- | A typeclass for values which can be converted to a 50 | -- 'Utf8Builder'. The intention of this typeclass is to provide a 51 | -- human-friendly display of the data. 52 | -- 53 | -- @since 0.1.0.0 54 | class Display a where 55 | {-# MINIMAL display | textDisplay #-} 56 | 57 | display :: a -> Utf8Builder 58 | display = display . textDisplay 59 | 60 | -- | Display data as `Text`, which will also be used for `display` if it is 61 | -- not overriden. 62 | -- 63 | -- @since 0.1.7.0 64 | textDisplay :: a -> Text 65 | textDisplay = utf8BuilderToText . display 66 | 67 | -- | @since 0.1.0.0 68 | instance Display Utf8Builder where 69 | display = id 70 | -- | @since 0.1.0.0 71 | instance Display Text where 72 | display = Utf8Builder . encodeUtf8Builder 73 | -- | @since 0.1.0.0 74 | instance Display TL.Text where 75 | display = foldMap display . TL.toChunks 76 | -- | @since 0.1.0.0 77 | instance Display Char where 78 | display = Utf8Builder . BB.charUtf8 79 | 80 | -- | @since 0.1.0.0 81 | instance Display Integer where 82 | display = Utf8Builder . BB.integerDec 83 | -- | @since 0.1.0.0 84 | instance Display Float where 85 | display = Utf8Builder . BB.floatDec 86 | instance Display Double where 87 | display = Utf8Builder . BB.doubleDec 88 | 89 | -- | @since 0.1.0.0 90 | instance Display Int where 91 | display = Utf8Builder . BB.intDec 92 | -- | @since 0.1.0.0 93 | instance Display Int8 where 94 | display = Utf8Builder . BB.int8Dec 95 | -- | @since 0.1.0.0 96 | instance Display Int16 where 97 | display = Utf8Builder . BB.int16Dec 98 | -- | @since 0.1.0.0 99 | instance Display Int32 where 100 | display = Utf8Builder . BB.int32Dec 101 | -- | @since 0.1.0.0 102 | instance Display Int64 where 103 | display = Utf8Builder . BB.int64Dec 104 | 105 | -- | @since 0.1.0.0 106 | instance Display Word where 107 | display = Utf8Builder . BB.wordDec 108 | -- | @since 0.1.0.0 109 | instance Display Word8 where 110 | display = Utf8Builder . BB.word8Dec 111 | -- | @since 0.1.0.0 112 | instance Display Word16 where 113 | display = Utf8Builder . BB.word16Dec 114 | -- | @since 0.1.0.0 115 | instance Display Word32 where 116 | display = Utf8Builder . BB.word32Dec 117 | -- | @since 0.1.0.0 118 | instance Display Word64 where 119 | display = Utf8Builder . BB.word64Dec 120 | 121 | -- | @since 0.1.0.0 122 | instance Display SomeException where 123 | display = fromString . displayException 124 | -- | @since 0.1.0.0 125 | instance Display IOException where 126 | display = fromString . displayException 127 | 128 | -- | @since 0.1.0.0 129 | instance Display (ProcessConfig a b c) where 130 | display = displayShow . setEnvInherit 131 | 132 | -- | Use the 'Show' instance for a value to convert it to a 133 | -- 'Utf8Builder'. 134 | -- 135 | -- @since 0.1.0.0 136 | displayShow :: Show a => a -> Utf8Builder 137 | displayShow = fromString . show 138 | 139 | -- | Convert a 'ByteString' into a 'Utf8Builder'. 140 | -- 141 | -- /NOTE/ This function performs no checks to ensure that the data is, 142 | -- in fact, UTF8 encoded. If you provide non-UTF8 data, later 143 | -- functions may fail. 144 | -- 145 | -- @since 0.1.0.0 146 | displayBytesUtf8 :: ByteString -> Utf8Builder 147 | displayBytesUtf8 = Utf8Builder . BB.byteString 148 | 149 | -- | Convert a 'Utf8Builder' value into a strict 'Text'. 150 | -- 151 | -- @since 0.1.0.0 152 | utf8BuilderToText :: Utf8Builder -> Text 153 | utf8BuilderToText = 154 | decodeUtf8With lenientDecode . BL.toStrict . BB.toLazyByteString . getUtf8Builder 155 | 156 | -- | Convert a 'Utf8Builder' value into a lazy 'Text'. 157 | -- 158 | -- @since 0.1.0.0 159 | utf8BuilderToLazyText :: Utf8Builder -> TL.Text 160 | utf8BuilderToLazyText = 161 | TL.decodeUtf8With lenientDecode . BB.toLazyByteString . getUtf8Builder 162 | 163 | -- | Write the given 'Utf8Builder' value to a file. 164 | -- 165 | -- @since 0.1.0.0 166 | writeFileUtf8Builder :: MonadIO m => FilePath -> Utf8Builder -> m () 167 | writeFileUtf8Builder fp (Utf8Builder builder) = 168 | liftIO $ withBinaryFile fp WriteMode $ \h -> BB.hPutBuilder h builder 169 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Exit.hs: -------------------------------------------------------------------------------- 1 | module RIO.Prelude.Exit 2 | ( exitFailure 3 | , exitSuccess 4 | , exitWith 5 | , System.Exit.ExitCode(..) 6 | ) where 7 | 8 | import Control.Monad.IO.Class 9 | import qualified System.Exit ( ExitCode (..) 10 | , exitFailure 11 | , exitSuccess 12 | , exitWith 13 | ) 14 | 15 | -- | Lifted version of "System.Exit.exitFailure". 16 | -- 17 | -- @since 0.1.9.0. 18 | exitFailure :: MonadIO m => m a 19 | exitFailure = liftIO System.Exit.exitFailure 20 | 21 | -- | Lifted version of "System.Exit.exitSuccess". 22 | -- 23 | -- @since 0.1.9.0. 24 | exitSuccess :: MonadIO m => m a 25 | exitSuccess = liftIO System.Exit.exitSuccess 26 | 27 | -- | Lifted version of "System.Exit.exitWith". 28 | -- 29 | -- @since 0.1.9.0. 30 | exitWith :: MonadIO m => System.Exit.ExitCode -> m a 31 | exitWith code = liftIO $ System.Exit.exitWith code 32 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Extra.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# LANGUAGE BangPatterns #-} 3 | module RIO.Prelude.Extra 4 | ( mapLeft 5 | , fromFirst 6 | , mapMaybeA 7 | , mapMaybeM 8 | , forMaybeA 9 | , forMaybeM 10 | , foldMapM 11 | , nubOrd 12 | , whenM 13 | , unlessM 14 | , (<&>) 15 | , asIO 16 | ) where 17 | 18 | import Prelude 19 | import qualified Data.Set as Set 20 | import Data.Monoid (First (..)) 21 | import Data.Foldable (foldlM) 22 | import Data.Functor 23 | import Data.Maybe 24 | import Control.Monad 25 | 26 | -- | Apply a function to a 'Left' constructor 27 | mapLeft :: (a1 -> a2) -> Either a1 b -> Either a2 b 28 | mapLeft f (Left a1) = Left (f a1) 29 | mapLeft _ (Right b) = Right b 30 | 31 | -- | Get a 'First' value with a default fallback 32 | fromFirst :: a -> First a -> a 33 | fromFirst x = fromMaybe x . getFirst 34 | 35 | -- | Applicative 'mapMaybe'. 36 | mapMaybeA :: Applicative f => (a -> f (Maybe b)) -> [a] -> f [b] 37 | mapMaybeA f = fmap catMaybes . traverse f 38 | 39 | -- | @'forMaybeA' '==' 'flip' 'mapMaybeA'@ 40 | forMaybeA :: Applicative f => [a] -> (a -> f (Maybe b)) -> f [b] 41 | forMaybeA = flip mapMaybeA 42 | 43 | -- | Monadic 'mapMaybe'. 44 | mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b] 45 | mapMaybeM f = liftM catMaybes . mapM f 46 | 47 | -- | @'forMaybeM' '==' 'flip' 'mapMaybeM'@ 48 | forMaybeM :: Monad m => [a] -> (a -> m (Maybe b)) -> m [b] 49 | forMaybeM = flip mapMaybeM 50 | 51 | -- | Extend 'foldMap' to allow side effects. 52 | -- 53 | -- Internally, this is implemented using a strict left fold. This is used for 54 | -- performance reasons. It also necessitates that this function has a @Monad@ 55 | -- constraint and not just an @Applicative@ constraint. For more information, 56 | -- see 57 | -- . 58 | -- 59 | -- @since 0.1.3.0 60 | foldMapM 61 | :: (Monad m, Monoid w, Foldable t) 62 | => (a -> m w) 63 | -> t a 64 | -> m w 65 | foldMapM f = foldlM 66 | (\acc a -> do 67 | w <- f a 68 | return $! mappend acc w) 69 | mempty 70 | 71 | -- | Strip out duplicates 72 | nubOrd :: Ord a => [a] -> [a] 73 | nubOrd = 74 | loop mempty 75 | where 76 | loop _ [] = [] 77 | loop !s (a:as) 78 | | a `Set.member` s = loop s as 79 | | otherwise = a : loop (Set.insert a s) as 80 | 81 | -- | Run the second value if the first value returns 'True' 82 | whenM :: Monad m => m Bool -> m () -> m () 83 | whenM boolM action = boolM >>= (`when` action) 84 | 85 | -- | Run the second value if the first value returns 'False' 86 | unlessM :: Monad m => m Bool -> m () -> m () 87 | unlessM boolM action = boolM >>= (`unless` action) 88 | 89 | #if !MIN_VERSION_base(4, 11, 0) 90 | (<&>) :: Functor f => f a -> (a -> b) -> f b 91 | as <&> f = f <$> as 92 | 93 | infixl 1 <&> 94 | #endif 95 | 96 | 97 | -- | Helper function to force an action to run in 'IO'. Especially 98 | -- useful for overly general contexts, like hspec tests. 99 | -- 100 | -- @since 0.1.3.0 101 | asIO :: IO a -> IO a 102 | asIO = id 103 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/IO.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module RIO.Prelude.IO 3 | ( withLazyFile 4 | , withLazyFileUtf8 5 | , readFileBinary 6 | , writeFileBinary 7 | , readFileUtf8 8 | , writeFileUtf8 9 | , hPutBuilder 10 | ) where 11 | 12 | import RIO.Prelude.Reexports 13 | import qualified Data.ByteString as B 14 | import qualified Data.ByteString.Builder as BB 15 | import qualified Data.ByteString.Lazy as BL 16 | import qualified Data.Text.Lazy as TL 17 | import qualified Data.Text.Lazy.IO as TL 18 | import qualified Data.Text.IO as T 19 | import System.IO (hSetEncoding, utf8) 20 | 21 | 22 | -- | Lazily get the contents of a file. Unlike 'BL.readFile', this 23 | -- ensures that if an exception is thrown, the file handle is closed 24 | -- immediately. 25 | withLazyFile :: MonadUnliftIO m => FilePath -> (BL.ByteString -> m a) -> m a 26 | withLazyFile fp inner = withBinaryFile fp ReadMode $ inner <=< liftIO . BL.hGetContents 27 | 28 | -- | Lazily read a file in UTF8 encoding. 29 | -- 30 | -- @since 0.1.13 31 | withLazyFileUtf8 :: MonadUnliftIO m => FilePath -> (TL.Text -> m a) -> m a 32 | withLazyFileUtf8 fp inner = withFile fp ReadMode $ \h -> 33 | inner =<< liftIO (hSetEncoding h utf8 >> TL.hGetContents h) 34 | 35 | -- | Write a file in UTF8 encoding 36 | -- 37 | -- This function will use OS-specific line ending handling. 38 | writeFileUtf8 :: MonadIO m => FilePath -> Text -> m () 39 | writeFileUtf8 fp text = liftIO $ withFile fp WriteMode $ \h -> do 40 | hSetEncoding h utf8 41 | T.hPutStr h text 42 | 43 | hPutBuilder :: MonadIO m => Handle -> Builder -> m () 44 | hPutBuilder h = liftIO . BB.hPutBuilder h 45 | {-# INLINE hPutBuilder #-} 46 | 47 | -- | Same as 'B.readFile', but generalized to 'MonadIO' 48 | readFileBinary :: MonadIO m => FilePath -> m ByteString 49 | readFileBinary = liftIO . B.readFile 50 | 51 | -- | Same as 'B.writeFile', but generalized to 'MonadIO' 52 | writeFileBinary :: MonadIO m => FilePath -> ByteString -> m () 53 | writeFileBinary fp = liftIO . B.writeFile fp 54 | 55 | -- | Read a file in UTF8 encoding, throwing an exception on invalid character 56 | -- encoding. 57 | -- 58 | -- This function will use OS-specific line ending handling. 59 | readFileUtf8 :: MonadIO m => FilePath -> m Text 60 | readFileUtf8 fp = liftIO $ withFile fp ReadMode $ \h -> do 61 | hSetEncoding h utf8 62 | T.hGetContents h 63 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Lens.hs: -------------------------------------------------------------------------------- 1 | module RIO.Prelude.Lens 2 | ( view 3 | , preview 4 | , Lens.Micro.ASetter 5 | , Lens.Micro.ASetter' 6 | , Lens.Micro.Getting 7 | , Lens.Micro.Lens 8 | , Lens.Micro.Lens' 9 | , Lens.Micro.SimpleGetter 10 | , Lens.Micro.lens 11 | , Lens.Micro.over 12 | , Lens.Micro.set 13 | , Lens.Micro.sets 14 | , Lens.Micro.to 15 | , (Lens.Micro.^.) 16 | , (Lens.Micro.^?) 17 | , (Lens.Micro.^..) 18 | , (Lens.Micro.%~) 19 | , (Lens.Micro..~) 20 | ) where 21 | 22 | import Lens.Micro 23 | import Lens.Micro.Mtl 24 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/RIO.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE MultiParamTypeClasses #-} 2 | {-# LANGUAGE FlexibleInstances #-} 3 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 4 | {-# LANGUAGE TypeFamilies #-} 5 | {-# LANGUAGE FunctionalDependencies #-} 6 | {-# LANGUAGE UndecidableInstances #-} 7 | module RIO.Prelude.RIO 8 | ( RIO (..) 9 | , runRIO 10 | , liftRIO 11 | , mapRIO 12 | -- SomeRef for Writer/State interfaces 13 | , SomeRef 14 | , HasStateRef (..) 15 | , HasWriteRef (..) 16 | , newSomeRef 17 | , newUnboxedSomeRef 18 | , readSomeRef 19 | , writeSomeRef 20 | , modifySomeRef 21 | ) where 22 | 23 | import GHC.Exts (RealWorld) 24 | 25 | import RIO.Prelude.Lens 26 | import RIO.Prelude.URef 27 | import RIO.Prelude.Reexports 28 | import Control.Monad.State (MonadState(..)) 29 | import Control.Monad.Writer (MonadWriter(..)) 30 | 31 | -- | The Reader+IO monad. This is different from a 'ReaderT' because: 32 | -- 33 | -- * It's not a transformer, it hardcodes IO for simpler usage and 34 | -- error messages. 35 | -- 36 | -- * Instances of typeclasses like 'MonadLogger' are implemented using 37 | -- classes defined on the environment, instead of using an 38 | -- underlying monad. 39 | newtype RIO env a = RIO { unRIO :: ReaderT env IO a } 40 | deriving (Functor,Applicative,Monad,MonadIO,MonadReader env,MonadThrow) 41 | 42 | instance Semigroup a => Semigroup (RIO env a) where 43 | (<>) = liftA2 (<>) 44 | instance Monoid a => Monoid (RIO env a) where 45 | mempty = pure mempty 46 | mappend = liftA2 mappend 47 | 48 | -- | Using the environment run in IO the action that requires that environment. 49 | -- 50 | -- @since 0.0.1.0 51 | runRIO :: MonadIO m => env -> RIO env a -> m a 52 | runRIO env (RIO (ReaderT f)) = liftIO (f env) 53 | 54 | -- | Abstract `RIO` to an arbitrary `MonadReader` instance, which can handle IO. 55 | -- 56 | -- @since 0.0.1.0 57 | liftRIO :: (MonadIO m, MonadReader env m) => RIO env a -> m a 58 | liftRIO rio = do 59 | env <- ask 60 | runRIO env rio 61 | 62 | -- | Lift one RIO env to another. 63 | -- 64 | -- @since 0.1.13.0 65 | mapRIO :: (outer -> inner) -> RIO inner a -> RIO outer a 66 | mapRIO f m = do 67 | outer <- ask 68 | runRIO (f outer) m 69 | 70 | instance MonadUnliftIO (RIO env) where 71 | withRunInIO inner = RIO $ withRunInIO $ \run -> inner (run . unRIO) 72 | {-# INLINE withRunInIO #-} 73 | 74 | instance PrimMonad (RIO env) where 75 | type PrimState (RIO env) = PrimState IO 76 | primitive = RIO . ReaderT . const . primitive 77 | 78 | -- | Abstraction over how to read from and write to a mutable reference 79 | -- 80 | -- @since 0.1.4.0 81 | data SomeRef a 82 | = SomeRef !(IO a) !(a -> IO ()) 83 | 84 | -- | Read from a SomeRef 85 | -- 86 | -- @since 0.1.4.0 87 | readSomeRef :: MonadIO m => SomeRef a -> m a 88 | readSomeRef (SomeRef x _) = liftIO x 89 | 90 | -- | Write to a SomeRef 91 | -- 92 | -- @since 0.1.4.0 93 | writeSomeRef :: MonadIO m => SomeRef a -> a -> m () 94 | writeSomeRef (SomeRef _ x) = liftIO . x 95 | 96 | -- | Modify a SomeRef 97 | -- This function is subject to change due to the lack of atomic operations 98 | -- 99 | -- @since 0.1.4.0 100 | modifySomeRef :: MonadIO m => SomeRef a -> (a -> a) -> m () 101 | modifySomeRef (SomeRef read' write) f = 102 | liftIO $ (f <$> read') >>= write 103 | 104 | ioRefToSomeRef :: IORef a -> SomeRef a 105 | ioRefToSomeRef ref = 106 | SomeRef (readIORef ref) 107 | (\val -> modifyIORef' ref (\_ -> val)) 108 | 109 | uRefToSomeRef :: Unbox a => URef RealWorld a -> SomeRef a 110 | uRefToSomeRef ref = 111 | SomeRef (readURef ref) (writeURef ref) 112 | 113 | -- | Environment values with stateful capabilities to SomeRef 114 | -- 115 | -- @since 0.1.4.0 116 | class HasStateRef s env | env -> s where 117 | stateRefL :: Lens' env (SomeRef s) 118 | 119 | -- | Identity state reference where the SomeRef is the env 120 | -- 121 | -- @since 0.1.4.0 122 | instance HasStateRef a (SomeRef a) where 123 | stateRefL = id 124 | 125 | -- | Environment values with writing capabilities to SomeRef 126 | -- 127 | -- @since 0.1.4.0 128 | class HasWriteRef w env | env -> w where 129 | writeRefL :: Lens' env (SomeRef w) 130 | 131 | -- | Identity write reference where the SomeRef is the env 132 | -- 133 | -- @since 0.1.4.0 134 | instance HasWriteRef a (SomeRef a) where 135 | writeRefL = id 136 | 137 | instance HasStateRef s env => MonadState s (RIO env) where 138 | get = do 139 | ref <- view stateRefL 140 | liftIO $ readSomeRef ref 141 | put st = do 142 | ref <- view stateRefL 143 | liftIO $ writeSomeRef ref st 144 | 145 | instance (Monoid w, HasWriteRef w env) => MonadWriter w (RIO env) where 146 | tell value = do 147 | ref <- view writeRefL 148 | liftIO $ modifySomeRef ref (`mappend` value) 149 | 150 | listen action = do 151 | w1 <- view writeRefL >>= liftIO . readSomeRef 152 | a <- action 153 | w2 <- do 154 | refEnv <- view writeRefL 155 | v <- liftIO $ readSomeRef refEnv 156 | _ <- liftIO $ writeSomeRef refEnv w1 157 | return v 158 | return (a, w2) 159 | 160 | pass action = do 161 | (a, transF) <- action 162 | ref <- view writeRefL 163 | liftIO $ modifySomeRef ref transF 164 | return a 165 | 166 | -- | create a new boxed SomeRef 167 | -- 168 | -- @since 0.1.4.0 169 | newSomeRef :: MonadIO m => a -> m (SomeRef a) 170 | newSomeRef a = do 171 | ioRefToSomeRef <$> newIORef a 172 | 173 | -- | create a new unboxed SomeRef 174 | -- 175 | -- @since 0.1.4.0 176 | newUnboxedSomeRef :: (MonadIO m, Unbox a) => a -> m (SomeRef a) 177 | newUnboxedSomeRef a = 178 | uRefToSomeRef <$> (liftIO $ newURef a) 179 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Reexports.hs: -------------------------------------------------------------------------------- 1 | module RIO.Prelude.Reexports 2 | ( module RIO.Prelude 3 | , module RIO.Prelude.Types 4 | , module UnliftIO 5 | , module UnliftIO.Concurrent 6 | ) where 7 | 8 | import RIO.Prelude 9 | import RIO.Prelude.Types 10 | import UnliftIO 11 | import UnliftIO.Concurrent 12 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Renames.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ConstraintKinds #-} 2 | module RIO.Prelude.Renames 3 | ( sappend 4 | , LByteString 5 | , LText 6 | , UVector 7 | , SVector 8 | , GVector 9 | , toStrictBytes 10 | , fromStrictBytes 11 | , yieldThread 12 | ) where 13 | 14 | import Prelude 15 | import qualified Data.ByteString as B 16 | import qualified Data.ByteString.Lazy as BL 17 | import qualified Data.Vector.Generic as GVector 18 | import qualified Data.Vector.Storable as SVector 19 | import qualified Data.Vector.Unboxed as UVector 20 | import qualified Data.Text.Lazy as TL 21 | import qualified Data.Semigroup 22 | import UnliftIO (MonadIO) 23 | import qualified UnliftIO.Concurrent (yield) 24 | 25 | sappend :: Data.Semigroup.Semigroup s => s -> s -> s 26 | sappend = (Data.Semigroup.<>) 27 | 28 | type UVector = UVector.Vector 29 | type SVector = SVector.Vector 30 | type GVector = GVector.Vector 31 | 32 | type LByteString = BL.ByteString 33 | type LText = TL.Text 34 | 35 | toStrictBytes :: LByteString -> B.ByteString 36 | toStrictBytes = BL.toStrict 37 | 38 | fromStrictBytes :: B.ByteString -> LByteString 39 | fromStrictBytes = BL.fromStrict 40 | 41 | yieldThread :: MonadIO m => m () 42 | yieldThread = UnliftIO.Concurrent.yield 43 | {-# INLINE yieldThread #-} 44 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Simple.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | -- | Provide a @`SimpleApp`@ datatype, for providing a basic @App@-like 3 | -- environment with common functionality built in. This is intended to 4 | -- make it easier to, e.g., use rio's logging and process code from 5 | -- within short scripts. 6 | -- 7 | -- @since 0.1.3.0 8 | module RIO.Prelude.Simple 9 | ( SimpleApp 10 | , mkSimpleApp 11 | , runSimpleApp 12 | ) where 13 | 14 | import RIO.Prelude.Reexports 15 | import RIO.Prelude.Logger 16 | import RIO.Prelude.Lens 17 | import RIO.Prelude.RIO 18 | import RIO.Process 19 | import System.Environment (lookupEnv) 20 | 21 | -- | A simple, non-customizable environment type for @RIO@, which 22 | -- provides common functionality. If it's insufficient for your needs, 23 | -- define your own, custom @App@ data type. 24 | -- 25 | -- @since 0.1.3.0 26 | data SimpleApp = SimpleApp 27 | { saLogFunc :: !LogFunc 28 | , saProcessContext :: !ProcessContext 29 | } 30 | instance HasLogFunc SimpleApp where 31 | logFuncL = lens saLogFunc (\x y -> x { saLogFunc = y }) 32 | instance HasProcessContext SimpleApp where 33 | processContextL = lens saProcessContext (\x y -> x { saProcessContext = y }) 34 | 35 | 36 | -- | Constructor for `SimpleApp`. In case when `ProcessContext` is not supplied 37 | -- `mkDefaultProcessContext` will be used to create it. 38 | -- 39 | -- @since 0.1.14.0 40 | mkSimpleApp :: MonadIO m => LogFunc -> Maybe ProcessContext -> m SimpleApp 41 | mkSimpleApp logFunc mProcessContext = do 42 | processContext <- maybe mkDefaultProcessContext pure mProcessContext 43 | pure $ SimpleApp {saLogFunc = logFunc, saProcessContext = processContext} 44 | 45 | 46 | -- | Run with a default configured @SimpleApp@, consisting of: 47 | -- 48 | -- * Logging to stderr 49 | -- 50 | -- * If the @RIO_VERBOSE@ environment variable is set, turns on 51 | -- verbose logging 52 | -- 53 | -- * Default process context 54 | -- 55 | -- @since 0.1.3.0 56 | runSimpleApp :: MonadIO m => RIO SimpleApp a -> m a 57 | runSimpleApp m = liftIO $ do 58 | verbose <- isJust <$> lookupEnv "RIO_VERBOSE" 59 | lo <- logOptionsHandle stderr verbose 60 | withLogFunc lo $ \lf -> do 61 | simpleApp <- mkSimpleApp lf Nothing 62 | runRIO simpleApp m 63 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Text.hs: -------------------------------------------------------------------------------- 1 | module RIO.Prelude.Text 2 | ( decodeUtf8Lenient 3 | , tshow 4 | ) where 5 | 6 | import Data.ByteString (ByteString) 7 | import qualified Data.Text as T 8 | import Data.Text.Encoding (decodeUtf8With) 9 | import Data.Text.Encoding.Error (lenientDecode) 10 | 11 | tshow :: Show a => a -> T.Text 12 | tshow = T.pack . show 13 | 14 | decodeUtf8Lenient :: ByteString -> T.Text 15 | decodeUtf8Lenient = decodeUtf8With lenientDecode 16 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Trace.hs: -------------------------------------------------------------------------------- 1 | module RIO.Prelude.Trace 2 | ( -- ** Trace 3 | -- *** Text 4 | trace 5 | , traceId 6 | , traceIO 7 | , traceM 8 | , traceEvent 9 | , traceEventIO 10 | , traceMarker 11 | , traceMarkerIO 12 | , traceStack 13 | -- *** Show 14 | , traceShow 15 | , traceShowId 16 | , traceShowIO 17 | , traceShowM 18 | , traceShowEvent 19 | , traceShowEventIO 20 | , traceShowMarker 21 | , traceShowMarkerIO 22 | , traceShowStack 23 | -- *** Display 24 | , traceDisplay 25 | , traceDisplayId 26 | , traceDisplayIO 27 | , traceDisplayM 28 | , traceDisplayEvent 29 | , traceDisplayEventIO 30 | , traceDisplayMarker 31 | , traceDisplayMarkerIO 32 | , traceDisplayStack 33 | ) where 34 | 35 | import qualified Debug.Trace as Trace 36 | 37 | import Control.Monad.IO.Class(MonadIO(..)) 38 | import RIO.Prelude.Display 39 | import RIO.Text (Text) 40 | import qualified RIO.Text as Text 41 | 42 | ---------------------------------------------------- 43 | -- Text 44 | ---------------------------------------------------- 45 | 46 | {-# WARNING trace "Trace statement left in code" #-} 47 | -- | @since 0.1.0.0 48 | trace :: Text -> a -> a 49 | trace = Trace.trace . Text.unpack 50 | 51 | {-# WARNING traceId "Trace statement left in code" #-} 52 | -- | @since 0.1.0.0 53 | traceId :: Text -> Text 54 | traceId str = Trace.trace (Text.unpack str) str 55 | 56 | {-# WARNING traceIO "Trace statement left in code" #-} 57 | -- | @since 0.1.0.0 58 | traceIO :: MonadIO m => Text -> m () 59 | traceIO = liftIO . Trace.traceIO . Text.unpack 60 | 61 | {-# WARNING traceM "Trace statement left in code" #-} 62 | -- | @since 0.1.0.0 63 | traceM :: Applicative f => Text -> f () 64 | traceM = Trace.traceM . Text.unpack 65 | 66 | {-# WARNING traceEvent "Trace statement left in code" #-} 67 | -- | @since 0.1.0.0 68 | traceEvent :: Text -> a -> a 69 | traceEvent = Trace.traceEvent . Text.unpack 70 | 71 | {-# WARNING traceEventIO "Trace statement left in code" #-} 72 | -- | @since 0.1.0.0 73 | traceEventIO :: MonadIO m => Text -> m () 74 | traceEventIO = liftIO . Trace.traceEventIO . Text.unpack 75 | 76 | {-# WARNING traceMarker "Trace statement left in code" #-} 77 | -- | @since 0.1.0.0 78 | traceMarker :: Text -> a -> a 79 | traceMarker = Trace.traceMarker . Text.unpack 80 | 81 | {-# WARNING traceMarkerIO "Trace statement left in code" #-} 82 | -- | @since 0.1.0.0 83 | traceMarkerIO :: MonadIO m => Text -> m () 84 | traceMarkerIO = liftIO . Trace.traceMarkerIO . Text.unpack 85 | 86 | {-# WARNING traceStack "Trace statement left in code" #-} 87 | -- | @since 0.1.0.0 88 | traceStack :: Text -> a -> a 89 | traceStack = Trace.traceStack . Text.unpack 90 | 91 | ---------------------------------------------------- 92 | -- Show 93 | ---------------------------------------------------- 94 | 95 | {-# WARNING traceShow "Trace statement left in code" #-} 96 | -- | @since 0.1.0.0 97 | traceShow :: Show a => a -> b -> b 98 | traceShow = Trace.traceShow 99 | 100 | {-# WARNING traceShowId "Trace statement left in code" #-} 101 | -- | @since 0.1.0.0 102 | traceShowId :: Show a => a -> a 103 | traceShowId = Trace.traceShowId 104 | 105 | {-# WARNING traceShowIO "Trace statement left in code" #-} 106 | -- | @since 0.1.0.0 107 | traceShowIO :: (Show a, MonadIO m) => a -> m () 108 | traceShowIO = liftIO . Trace.traceIO . show 109 | 110 | {-# WARNING traceShowM "Trace statement left in code" #-} 111 | -- | @since 0.1.0.0 112 | traceShowM :: (Show a, Applicative f) => a -> f () 113 | traceShowM = Trace.traceM . show 114 | 115 | {-# WARNING traceShowEvent "Trace statement left in code" #-} 116 | -- | @since 0.1.0.0 117 | traceShowEvent :: Show a => a -> b -> b 118 | traceShowEvent = Trace.traceEvent . show 119 | 120 | {-# WARNING traceShowEventIO "Trace statement left in code" #-} 121 | -- | @since 0.1.0.0 122 | traceShowEventIO :: (Show a, MonadIO m) => a -> m () 123 | traceShowEventIO = liftIO . Trace.traceEventIO . show 124 | 125 | {-# WARNING traceShowMarker "Trace statement left in code" #-} 126 | -- | @since 0.1.0.0 127 | traceShowMarker :: Show a => a -> b -> b 128 | traceShowMarker = Trace.traceMarker . show 129 | 130 | {-# WARNING traceShowMarkerIO "Trace statement left in code" #-} 131 | -- | @since 0.1.0.0 132 | traceShowMarkerIO :: (Show a, MonadIO m) => a -> m () 133 | traceShowMarkerIO = liftIO . Trace.traceMarkerIO . show 134 | 135 | {-# WARNING traceShowStack "Trace statement left in code" #-} 136 | -- | @since 0.1.0.0 137 | traceShowStack :: Show a => a -> b -> b 138 | traceShowStack = Trace.traceStack . show 139 | 140 | ---------------------------------------------------- 141 | -- Display 142 | ---------------------------------------------------- 143 | 144 | {-# WARNING traceDisplay "Trace statement left in code" #-} 145 | -- | @since 0.1.0.0 146 | traceDisplay :: Display a => a -> b -> b 147 | traceDisplay = trace . utf8BuilderToText . display 148 | 149 | {-# WARNING traceDisplayId "Trace statement left in code" #-} 150 | -- | @since 0.1.0.0 151 | traceDisplayId :: Display a => a -> a 152 | traceDisplayId x = traceDisplay x x 153 | 154 | {-# WARNING traceDisplayIO "Trace statement left in code" #-} 155 | -- | @since 0.1.0.0 156 | traceDisplayIO :: (Display a, MonadIO m) => a -> m () 157 | traceDisplayIO = traceIO . utf8BuilderToText . display 158 | 159 | {-# WARNING traceDisplayM "Trace statement left in code" #-} 160 | -- | @since 0.1.0.0 161 | traceDisplayM :: (Display a, Applicative f) => a -> f () 162 | traceDisplayM = traceM . utf8BuilderToText . display 163 | 164 | {-# WARNING traceDisplayEvent "Trace statement left in code" #-} 165 | -- | @since 0.1.0.0 166 | traceDisplayEvent :: Display a => a -> b -> b 167 | traceDisplayEvent = traceEvent . utf8BuilderToText . display 168 | 169 | {-# WARNING traceDisplayEventIO "Trace statement left in code" #-} 170 | -- | @since 0.1.0.0 171 | traceDisplayEventIO :: (Display a, MonadIO m) => a -> m () 172 | traceDisplayEventIO = traceEventIO . utf8BuilderToText . display 173 | 174 | {-# WARNING traceDisplayMarker "Trace statement left in code" #-} 175 | -- | @since 0.1.0.0 176 | traceDisplayMarker :: Display a => a -> b -> b 177 | traceDisplayMarker = traceMarker . utf8BuilderToText . display 178 | 179 | {-# WARNING traceDisplayMarkerIO "Trace statement left in code" #-} 180 | -- | @since 0.1.0.0 181 | traceDisplayMarkerIO :: (Display a, MonadIO m) => a -> m () 182 | traceDisplayMarkerIO = traceMarkerIO . utf8BuilderToText . display 183 | 184 | {-# WARNING traceDisplayStack "Trace statement left in code" #-} 185 | -- | @since 0.1.0.0 186 | traceDisplayStack :: Display a => a -> b -> b 187 | traceDisplayStack = traceStack . utf8BuilderToText . display 188 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/Types.hs: -------------------------------------------------------------------------------- 1 | module RIO.Prelude.Types 2 | ( 3 | -- * @base@ 4 | -- ** Types 5 | -- *** @Bool@ 6 | -- | Re-exported from "Data.Bool": 7 | Data.Bool.Bool(..) 8 | -- *** @Char@ (@String@) 9 | -- | Re-exported from "Data.Char": 10 | , Data.Char.Char 11 | -- | Re-exported from "Data.String": 12 | , Data.String.String 13 | -- | Re-exported from "System.IO": 14 | , System.IO.FilePath 15 | -- *** @Ordering@ 16 | -- | Re-exported from "Data.Ord": 17 | , Data.Ord.Ordering(..) 18 | -- *** Numbers 19 | -- **** @Int@ 20 | -- | Re-exported from "Data.Int": 21 | , Data.Int.Int 22 | -- ***** @Int8@ 23 | , Data.Int.Int8 24 | -- ***** @Int16@ 25 | , Data.Int.Int16 26 | -- ***** @Int32@ 27 | , Data.Int.Int32 28 | -- ***** @Int64@ 29 | , Data.Int.Int64 30 | -- **** @Word@ 31 | -- | Re-exported from "Data.Word": 32 | , Data.Word.Word 33 | -- ***** @Word8@ 34 | , Data.Word.Word8 35 | -- ***** @Word16@ 36 | , Data.Word.Word16 37 | -- ***** @Word32@ 38 | , Data.Word.Word32 39 | -- ***** @Word64@ 40 | , Data.Word.Word64 41 | -- **** @Integer@ 42 | -- | Re-exported from "Prelude.Integer": 43 | , Prelude.Integer 44 | -- **** @Natural@ 45 | -- | Re-exported from "Numeric.Natural": 46 | , Numeric.Natural.Natural 47 | -- **** @Rational@ 48 | -- | Re-exported from "Data.Ratio": 49 | , Data.Ratio.Rational 50 | -- **** @Float@ 51 | -- | Re-exported from "Prelude": 52 | , Prelude.Float 53 | -- **** @Double@ 54 | -- | Re-exported from "Prelude": 55 | , Prelude.Double 56 | 57 | -- *** @Maybe@ 58 | -- | Re-exported from "Data.Maybe": 59 | , Data.Maybe.Maybe(..) 60 | -- *** @Either@ 61 | -- | Re-exported from "Data.Either": 62 | , Data.Either.Either(..) 63 | -- *** @NonEmpty@ 64 | -- | Re-exported from Data.List.NonEmpty 65 | , Data.List.NonEmpty.NonEmpty(..) 66 | -- *** @Proxy@ 67 | -- | Re-exported from "Data.Proxy": 68 | , Data.Proxy.Proxy(..) 69 | -- *** @Void@ 70 | -- | Re-exported from "Data.Void": 71 | , Data.Void.Void 72 | -- *** @Const@ 73 | -- | Re-exported from "Data.Functor.Const": 74 | , Data.Functor.Const.Const(..) 75 | -- *** @Identity@ 76 | -- | Re-exported from "Data.Functor.Identity": 77 | , Data.Functor.Identity.Identity(..) 78 | -- *** @IO@ 79 | -- | Re-exported from "System.IO": 80 | , System.IO.IO 81 | -- *** @ST@ 82 | -- | Re-exported from "Control.Monad.ST": 83 | , Control.Monad.ST.ST 84 | 85 | -- ** Type Classes 86 | 87 | -- *** @Eq@ 88 | -- | Re-exported from "Data.Eq": 89 | , Data.Eq.Eq 90 | 91 | -- *** @Ord@ 92 | -- | Re-exported from "Data.Ord": 93 | , Data.Ord.Ord 94 | 95 | -- *** @Bounded@ 96 | -- | Re-exported from "Prelude": 97 | , Prelude.Bounded 98 | 99 | -- *** @Enum@ 100 | -- | Re-exported from "Prelude": 101 | , Prelude.Enum 102 | 103 | -- *** Strings 104 | -- **** @Show@ 105 | -- | Re-exported from "Text.Show": 106 | , Text.Show.Show 107 | -- **** @Read@ 108 | -- | Re-exported from "Text.Read": 109 | , Text.Read.Read 110 | -- **** @IsString@ 111 | -- | Re-exported from "Data.String": 112 | , Data.String.IsString 113 | 114 | -- *** Numeric 115 | -- | All numeric classes are re-exported from "Prelude": 116 | 117 | -- **** @Num@ 118 | , Prelude.Num 119 | -- **** @Fractional@ 120 | , Prelude.Fractional 121 | -- **** @Floating@ 122 | , Prelude.Floating 123 | -- **** @Real@ 124 | , Prelude.Real 125 | -- **** @Integral@ 126 | , Prelude.Integral 127 | -- **** @RealFrac@ 128 | , Prelude.RealFrac 129 | -- **** @RealFloat@ 130 | , Prelude.RealFloat 131 | 132 | -- *** Categories 133 | -- **** @Functor@ 134 | -- | Re-exported from "Data.Functor": 135 | , Data.Functor.Functor 136 | -- **** @Bifunctor@ 137 | -- | Re-exported from "Data.Bifunctor": 138 | , Data.Bifunctor.Bifunctor 139 | -- **** @Foldable@ 140 | -- | Re-exported from "Data.Foldable": 141 | , Data.Foldable.Foldable 142 | -- **** @Bifoldable@ 143 | -- | Re-exported from "Data.Bifoldable": 144 | , Data.Bifoldable.Bifoldable 145 | -- **** @Semigroup@ 146 | -- | Re-exported from "Data.Semigroup": 147 | , Data.Semigroup.Semigroup 148 | -- **** @Monoid@ 149 | -- | Re-exported from "Data.Monoid": 150 | , Data.Monoid.Monoid 151 | -- **** @Applicative@ 152 | -- | Re-exported from "Control.Applicative": 153 | , Control.Applicative.Applicative 154 | -- **** @Alternative@ 155 | -- | Re-exported from "Control.Applicative": 156 | , Control.Applicative.Alternative 157 | -- **** @Traversable@ 158 | -- | Re-exported from "Data.Traversable": 159 | , Data.Traversable.Traversable 160 | -- **** @Bitraversable@ 161 | -- | Re-exported from "Data.Bitraversable": 162 | , Data.Bitraversable.Bitraversable 163 | -- **** @Monad@ 164 | -- | Re-exported from "Control.Monad": 165 | , Control.Monad.Monad 166 | -- **** @MonadPlus@ 167 | -- | Re-exported from "Control.Monad": 168 | , Control.Monad.MonadPlus 169 | -- **** @Category@ 170 | -- | Re-exported from "Control.Category": 171 | , Control.Category.Category 172 | -- **** @Arrow@ 173 | -- | Re-exported from "Control.Arrow": 174 | , Control.Arrow.Arrow 175 | -- **** @MonadFail@ 176 | -- | Re-exported from "Control.Monad.Fail": 177 | , Control.Monad.Fail.MonadFail 178 | 179 | -- *** Data 180 | -- **** @Typeable@ 181 | -- | Re-exported from "Control.Monad": 182 | , Data.Typeable.Typeable 183 | -- **** @Data@ 184 | -- | Re-exported from "Data.Data": 185 | , Data.Data.Data(..) 186 | -- **** @Generic@ 187 | -- | Re-exported from "GHC.Generics": 188 | , GHC.Generics.Generic 189 | -- **** @Storable@ 190 | -- | Re-exported from "Foreign.Storable": 191 | , Foreign.Storable.Storable 192 | 193 | -- *** Exceptions 194 | -- *** @Exception@ 195 | -- | Re-exported from "Control.Exception.Base": 196 | , Control.Exception.Base.Exception 197 | -- **** @HasCallStack@ 198 | -- | Re-exported from "GHC.Stack": 199 | , GHC.Stack.HasCallStack 200 | 201 | 202 | -- * @deepseq@ 203 | -- ** @NFData@ 204 | -- | Re-exported from "Control.DeepSeq": 205 | , Control.DeepSeq.NFData 206 | 207 | -- * @mtl@ 208 | -- ** @MonadTrans@ 209 | -- | Re-exported from "Control.Monad.Reader": 210 | , Control.Monad.Reader.MonadTrans 211 | -- ** @MonadReader@ 212 | , Control.Monad.Reader.MonadReader 213 | -- ** @ReaderT@ (@Reader@) 214 | -- | Re-exported from "Control.Monad.Reader": 215 | , Control.Monad.Reader.Reader 216 | , Control.Monad.Reader.ReaderT(ReaderT) 217 | 218 | -- * @exceptions@ 219 | -- ** @MonadThrow@ 220 | -- | Re-exported from "Control.Monad.Catch": 221 | , Control.Monad.Catch.MonadThrow 222 | 223 | -- * @bytestring@ 224 | -- ** @ByteString@ 225 | -- | Re-exported from "Data.ByteString": 226 | , Data.ByteString.ByteString 227 | -- ** @LByteString@ 228 | -- | A synonym for lazy `Data.ByteString.Lazy.ByteString` re-exported from "Data.ByteString.Lazy": 229 | , RIO.Prelude.Renames.LByteString 230 | -- ** @Builder@ 231 | -- | Re-exported from "Data.ByteString.Builder": 232 | , Data.ByteString.Builder.Builder 233 | -- ** @ShortByteString@ 234 | -- | Re-exported from "Data.ByteString.Short": 235 | , Data.ByteString.Short.ShortByteString 236 | 237 | -- * @text@ 238 | -- ** @Text@ 239 | -- | Re-exported from "Data.Text": 240 | , Data.Text.Text 241 | -- ** @LText@ 242 | -- | A synonym for lazy `Data.Text.Lazy.Text` re-exported from "Data.Text.Lazy": 243 | , RIO.Prelude.Renames.LText 244 | -- ** @UncodeException@ 245 | -- | Re-exported from "Data.Text.Encoding.Error": 246 | , Data.Text.Encoding.Error.UnicodeException(..) 247 | 248 | -- * @vector@ 249 | -- ** @Vector@ 250 | -- | Boxed vector re-exported from "Data.Vector": 251 | , Data.Vector.Vector 252 | -- ** @UVector@ 253 | -- | A synonym for unboxed `Data.Vector.Unboxed.Vector` re-exported from "Data.Vector.Unboxed": 254 | , RIO.Prelude.Renames.UVector 255 | -- *** @Unbox@ 256 | , Data.Vector.Unboxed.Unbox 257 | -- ** @SVector@ 258 | -- | A synonym for storable `Data.Vector.Storable.Vector` re-exported from "Data.Vector.Storable": 259 | , RIO.Prelude.Renames.SVector 260 | -- ** @GVector@ 261 | -- | A synonym for generic `Data.Vector.Generic.Vector` re-exported from "Data.Vector.Generic": 262 | , RIO.Prelude.Renames.GVector 263 | 264 | -- * @containers@ 265 | -- ** @IntMap@ 266 | -- | Re-exported from "Data.IntMap.Strict": 267 | , Data.IntMap.Strict.IntMap 268 | -- ** @Map@ 269 | -- | Re-exported from "Data.Map.Strict": 270 | , Data.Map.Strict.Map 271 | -- ** @IntSet@ 272 | -- | Re-exported from "Data.IntSet": 273 | , Data.IntSet.IntSet 274 | -- ** @Set@ 275 | -- | Re-exported from "Data.Set": 276 | , Data.Set.Set 277 | -- ** @Seq@ 278 | -- | Re-exported from "Data.Seq": 279 | , Data.Sequence.Seq 280 | 281 | -- * @hashable@ 282 | -- ** @Hashable@ 283 | , Data.Hashable.Hashable 284 | 285 | -- * @unordered-containers@ 286 | -- ** @HashMap@ 287 | -- | Re-exported from "Data.HashMap.Strict": 288 | , Data.HashMap.Strict.HashMap 289 | -- ** @HashSet@ 290 | -- | Re-exported from "Data.HashSet": 291 | , Data.HashSet.HashSet 292 | 293 | -- * @primitive@ 294 | -- ** @PrimMonad@ 295 | -- | Re-exported from "Control.Monad.Primitive": 296 | , Control.Monad.Primitive.PrimMonad (PrimState) 297 | ) where 298 | 299 | import qualified RIO.Prelude.Renames 300 | 301 | import qualified Control.Applicative 302 | import qualified Control.Arrow 303 | import qualified Control.Category 304 | import qualified Control.DeepSeq 305 | import qualified Control.Exception.Base 306 | import qualified Control.Monad 307 | import qualified Control.Monad.Catch 308 | import qualified Control.Monad.Fail 309 | import qualified Control.Monad.Primitive (PrimMonad(..)) 310 | import qualified Control.Monad.Reader 311 | import qualified Control.Monad.ST 312 | import qualified Data.Bifoldable 313 | import qualified Data.Bifunctor 314 | import qualified Data.Bitraversable 315 | import qualified Data.Bool 316 | import qualified Data.ByteString (ByteString) 317 | import qualified Data.ByteString.Builder (Builder) 318 | import qualified Data.ByteString.Short 319 | import qualified Data.Char 320 | import qualified Data.Data 321 | import qualified Data.Either 322 | import qualified Data.Eq 323 | import qualified Data.Foldable 324 | import qualified Data.Function 325 | import qualified Data.Functor 326 | import qualified Data.Functor.Const 327 | import qualified Data.Functor.Identity 328 | import qualified Data.Hashable 329 | import qualified Data.HashMap.Strict 330 | import qualified Data.HashSet 331 | import qualified Data.Int 332 | import qualified Data.IntMap.Strict 333 | import qualified Data.IntSet 334 | import qualified Data.List 335 | import qualified Data.List.NonEmpty 336 | import qualified Data.Map.Strict 337 | import qualified Data.Maybe 338 | import qualified Data.Monoid (Monoid) 339 | import qualified Data.Ord 340 | import qualified Data.Proxy 341 | import qualified Data.Ratio 342 | import qualified Data.Semigroup (Semigroup) 343 | import qualified Data.Sequence 344 | import qualified Data.Set 345 | import qualified Data.String (IsString, String) 346 | import qualified Data.Text (Text) 347 | import qualified Data.Text.Encoding.Error 348 | import qualified Data.Traversable 349 | import qualified Data.Typeable 350 | import qualified Data.Vector 351 | import qualified Data.Vector.Unboxed (Unbox) 352 | import qualified Data.Void 353 | import qualified Data.Word 354 | import qualified Foreign.Storable 355 | import qualified GHC.Generics 356 | import qualified GHC.Stack 357 | import qualified Numeric.Natural 358 | import qualified Prelude 359 | import qualified System.Exit 360 | import qualified System.IO 361 | import qualified Text.Read 362 | import qualified Text.Show 363 | 364 | -- Bring instances for some of the unliftio types in scope, so they can be documented here. 365 | import UnliftIO () 366 | -------------------------------------------------------------------------------- /rio/src/RIO/Prelude/URef.hs: -------------------------------------------------------------------------------- 1 | module RIO.Prelude.URef 2 | ( URef 3 | , IOURef 4 | , newURef 5 | , readURef 6 | , writeURef 7 | , modifyURef 8 | ) where 9 | 10 | import RIO.Prelude.Reexports 11 | import qualified Data.Vector.Unboxed.Mutable as MUVector 12 | 13 | -- | An unboxed reference. This works like an 'IORef', but the data is 14 | -- stored in a bytearray instead of a heap object, avoiding 15 | -- significant allocation overhead in some cases. For a concrete 16 | -- example, see this Stack Overflow question: 17 | -- . 18 | -- 19 | -- The first parameter is the state token type, the same as would be 20 | -- used for the 'ST' monad. If you're using an 'IO'-based monad, you 21 | -- can use the convenience 'IOURef' type synonym instead. 22 | -- 23 | -- @since 0.0.2.0 24 | newtype URef s a = URef (MUVector.MVector s a) 25 | 26 | -- | Helpful type synonym for using a 'URef' from an 'IO'-based stack. 27 | -- 28 | -- @since 0.0.2.0 29 | type IOURef = URef (PrimState IO) 30 | 31 | -- | Create a new 'URef' 32 | -- 33 | -- @since 0.0.2.0 34 | newURef :: (PrimMonad m, Unbox a) => a -> m (URef (PrimState m) a) 35 | newURef a = fmap URef (MUVector.replicate 1 a) 36 | 37 | -- | Read the value in a 'URef' 38 | -- 39 | -- @since 0.0.2.0 40 | readURef :: (PrimMonad m, Unbox a) => URef (PrimState m) a -> m a 41 | readURef (URef v) = MUVector.unsafeRead v 0 42 | 43 | -- | Write a value into a 'URef'. Note that this action is strict, and 44 | -- will force evalution of the value. 45 | -- 46 | -- @since 0.0.2.0 47 | writeURef :: (PrimMonad m, Unbox a) => URef (PrimState m) a -> a -> m () 48 | writeURef (URef v) = MUVector.unsafeWrite v 0 49 | 50 | -- | Modify a value in a 'URef'. Note that this action is strict, and 51 | -- will force evaluation of the result value. 52 | -- 53 | -- @since 0.0.2.0 54 | modifyURef :: (PrimMonad m, Unbox a) => URef (PrimState m) a -> (a -> a) -> m () 55 | modifyURef u f = readURef u >>= writeURef u . f 56 | -------------------------------------------------------------------------------- /rio/src/RIO/Seq.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | -- | @Seq@. Import as: 3 | -- 4 | -- > import qualified RIO.Seq as Seq 5 | module RIO.Seq 6 | ( 7 | Data.Sequence.Seq(..) 8 | 9 | -- * Construction 10 | , Data.Sequence.empty 11 | , Data.Sequence.singleton 12 | , (Data.Sequence.<|) 13 | , (Data.Sequence.|>) 14 | , (Data.Sequence.><) 15 | , Data.Sequence.fromList 16 | , Data.Sequence.fromFunction 17 | , Data.Sequence.fromArray 18 | 19 | -- ** Repetition 20 | , Data.Sequence.replicate 21 | , Data.Sequence.replicateA 22 | , Data.Sequence.replicateM 23 | #if MIN_VERSION_containers(0, 5, 8) 24 | , Data.Sequence.cycleTaking 25 | #endif 26 | 27 | -- ** Iterative construction 28 | , Data.Sequence.iterateN 29 | , Data.Sequence.unfoldr 30 | , Data.Sequence.unfoldl 31 | 32 | -- * Deconstruction 33 | -- | Additional functions for deconstructing sequences are available via the 34 | -- 'Foldable' instance of 'Seq'. 35 | 36 | -- ** Queries 37 | , Data.Sequence.null 38 | , Data.Sequence.length 39 | -- ** Views 40 | , Data.Sequence.ViewL(..) 41 | , Data.Sequence.viewl 42 | , Data.Sequence.ViewR(..) 43 | , Data.Sequence.viewr 44 | 45 | -- * Scans 46 | , Data.Sequence.scanl 47 | , Data.Sequence.scanl1 48 | , Data.Sequence.scanr 49 | , Data.Sequence.scanr1 50 | 51 | -- * Sublists 52 | , Data.Sequence.tails 53 | , Data.Sequence.inits 54 | #if MIN_VERSION_containers(0, 5, 8) 55 | , Data.Sequence.chunksOf 56 | #endif 57 | 58 | -- ** Sequential searches 59 | , Data.Sequence.takeWhileL 60 | , Data.Sequence.takeWhileR 61 | , Data.Sequence.dropWhileL 62 | , Data.Sequence.dropWhileR 63 | , Data.Sequence.spanl 64 | , Data.Sequence.spanr 65 | , Data.Sequence.breakl 66 | , Data.Sequence.breakr 67 | , Data.Sequence.partition 68 | , Data.Sequence.filter 69 | 70 | -- * Sorting 71 | , Data.Sequence.sort 72 | , Data.Sequence.sortBy 73 | , Data.Sequence.unstableSort 74 | , Data.Sequence.unstableSortBy 75 | 76 | -- * Indexing 77 | #if MIN_VERSION_containers(0, 5, 8) 78 | , Data.Sequence.lookup 79 | , (Data.Sequence.!?) 80 | #endif 81 | , Data.Sequence.index 82 | , Data.Sequence.adjust 83 | 84 | #if MIN_VERSION_containers(0, 5, 8) 85 | , Data.Sequence.adjust' 86 | #endif 87 | , Data.Sequence.update 88 | , Data.Sequence.take 89 | , Data.Sequence.drop 90 | #if MIN_VERSION_containers(0, 5, 8) 91 | , Data.Sequence.insertAt 92 | , Data.Sequence.deleteAt 93 | #endif 94 | , Data.Sequence.splitAt 95 | 96 | -- ** Indexing with predicates 97 | -- | These functions perform sequential searches from the left or right ends 98 | -- of the sequence elements. 99 | , Data.Sequence.elemIndexL 100 | , Data.Sequence.elemIndicesL 101 | , Data.Sequence.elemIndexR 102 | , Data.Sequence.elemIndicesR 103 | , Data.Sequence.findIndexL 104 | , Data.Sequence.findIndicesL 105 | , Data.Sequence.findIndexR 106 | , Data.Sequence.findIndicesR 107 | 108 | -- * Folds 109 | -- | General folds are available via the 'Foldable' instance of 'Seq'. 110 | #if MIN_VERSION_containers(0, 5, 8) 111 | , Data.Sequence.foldMapWithIndex 112 | #endif 113 | , Data.Sequence.foldlWithIndex 114 | , Data.Sequence.foldrWithIndex 115 | 116 | -- * Transformations 117 | , Data.Sequence.mapWithIndex 118 | #if MIN_VERSION_containers(0, 5, 8) 119 | , Data.Sequence.traverseWithIndex 120 | #endif 121 | , Data.Sequence.reverse 122 | #if MIN_VERSION_containers(0, 5, 8) 123 | , Data.Sequence.intersperse 124 | #endif 125 | 126 | -- ** Zips 127 | , Data.Sequence.zip 128 | , Data.Sequence.zipWith 129 | , Data.Sequence.zip3 130 | , Data.Sequence.zipWith3 131 | , Data.Sequence.zip4 132 | , Data.Sequence.zipWith4 133 | ) where 134 | 135 | import qualified Data.Sequence 136 | -------------------------------------------------------------------------------- /rio/src/RIO/Set.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | 3 | -- | @Set@. Import as: 4 | -- 5 | -- > import qualified RIO.Set as Set 6 | -- 7 | -- This module does not export any partial or unchecked functions. For those, 8 | -- see "RIO.Set.Partial" and "RIO.Set.Unchecked" 9 | module RIO.Set 10 | ( 11 | -- * Set type 12 | Data.Set.Set 13 | 14 | -- * Operators 15 | , (Data.Set.\\) 16 | 17 | -- * Query 18 | , Data.Set.null 19 | , Data.Set.size 20 | , Data.Set.member 21 | , Data.Set.notMember 22 | , Data.Set.lookupLT 23 | , Data.Set.lookupGT 24 | , Data.Set.lookupLE 25 | , Data.Set.lookupGE 26 | , Data.Set.isSubsetOf 27 | , Data.Set.isProperSubsetOf 28 | 29 | -- * Construction 30 | , Data.Set.empty 31 | , Data.Set.singleton 32 | , Data.Set.insert 33 | , Data.Set.delete 34 | 35 | -- * Combine 36 | , Data.Set.union 37 | , Data.Set.unions 38 | , Data.Set.difference 39 | , Data.Set.intersection 40 | 41 | -- * Filter 42 | , Data.Set.filter 43 | #if MIN_VERSION_containers(0,5,8) 44 | , Data.Set.takeWhileAntitone 45 | , Data.Set.dropWhileAntitone 46 | , Data.Set.spanAntitone 47 | #endif 48 | , Data.Set.partition 49 | , Data.Set.split 50 | , Data.Set.splitMember 51 | , Data.Set.splitRoot 52 | 53 | -- * Indexed 54 | , Data.Set.lookupIndex 55 | #if MIN_VERSION_containers(0,5,8) 56 | , Data.Set.take 57 | , Data.Set.drop 58 | , Data.Set.splitAt 59 | #endif 60 | 61 | -- * Map 62 | , Data.Set.map 63 | 64 | -- * Folds 65 | , Data.Set.foldr 66 | , Data.Set.foldl 67 | -- ** Strict folds 68 | , Data.Set.foldr' 69 | , Data.Set.foldl' 70 | 71 | -- * Min\/Max 72 | #if MIN_VERSION_containers(0,5,9) 73 | , Data.Set.lookupMin 74 | , Data.Set.lookupMax 75 | #endif 76 | , Data.Set.deleteMin 77 | , Data.Set.deleteMax 78 | , Data.Set.maxView 79 | , Data.Set.minView 80 | 81 | -- * Conversion 82 | 83 | -- ** List 84 | , Data.Set.elems 85 | , Data.Set.toList 86 | , Data.Set.fromList 87 | 88 | -- ** Ordered list 89 | , Data.Set.toAscList 90 | , Data.Set.toDescList 91 | 92 | -- * Debugging 93 | , Data.Set.showTree 94 | , Data.Set.showTreeWith 95 | , Data.Set.valid 96 | ) where 97 | 98 | import qualified Data.Set 99 | -------------------------------------------------------------------------------- /rio/src/RIO/Set/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | @Set@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Set.Partial as Set' 4 | module RIO.Set.Partial 5 | ( 6 | -- * Indexed 7 | Data.Set.findIndex 8 | , Data.Set.elemAt 9 | , Data.Set.deleteAt 10 | 11 | -- * Min\/Max 12 | , Data.Set.findMin 13 | , Data.Set.findMax 14 | , Data.Set.deleteFindMin 15 | , Data.Set.deleteFindMax 16 | ) where 17 | 18 | import qualified Data.Set 19 | -------------------------------------------------------------------------------- /rio/src/RIO/Set/Unchecked.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | 3 | -- | This module contains functions from "Data.Set" that have unchecked 4 | -- preconditions on their input. If these preconditions are not satisfied, 5 | -- the data structure may end up in an invalid state and other operations 6 | -- may misbehave. Import as: 7 | -- 8 | -- > import qualified RIO.Set.Unchecked as Set' 9 | module RIO.Set.Unchecked 10 | ( 11 | -- * Map 12 | Data.Set.mapMonotonic 13 | 14 | -- * Ordered list 15 | , Data.Set.fromAscList 16 | #if MIN_VERSION_containers(0,5,8) 17 | , Data.Set.fromDescList 18 | #endif 19 | , Data.Set.fromDistinctAscList 20 | #if MIN_VERSION_containers(0,5,8) 21 | , Data.Set.fromDistinctDescList 22 | #endif 23 | ) where 24 | 25 | import qualified Data.Set 26 | -------------------------------------------------------------------------------- /rio/src/RIO/State.hs: -------------------------------------------------------------------------------- 1 | -- | Provides reexports of 'MonadState' and related helpers. 2 | -- 3 | -- @since 0.1.4.0 4 | module RIO.State 5 | ( 6 | Control.Monad.State.MonadState (..) 7 | , Control.Monad.State.gets 8 | , Control.Monad.State.modify 9 | , Control.Monad.State.modify' 10 | , Control.Monad.State.State 11 | , Control.Monad.State.runState 12 | , Control.Monad.State.evalState 13 | , Control.Monad.State.execState 14 | , Control.Monad.State.mapState 15 | , Control.Monad.State.withState 16 | , Control.Monad.State.StateT (..) 17 | , Control.Monad.State.evalStateT 18 | , Control.Monad.State.execStateT 19 | , Control.Monad.State.mapStateT 20 | , Control.Monad.State.withStateT 21 | ) where 22 | 23 | import qualified Control.Monad.State 24 | -------------------------------------------------------------------------------- /rio/src/RIO/Text.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE MagicHash #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | 4 | -- | Strict @Text@. Import as: 5 | -- 6 | -- > import qualified RIO.Text as T 7 | -- 8 | -- This module does not export any partial functions. For those, see 9 | -- "RIO.Text.Partial" 10 | module RIO.Text 11 | ( 12 | -- * Types 13 | Data.Text.Text 14 | 15 | -- * Creation and elimination 16 | , Data.Text.pack 17 | , Data.Text.unpack 18 | , Data.Text.singleton 19 | , Data.Text.empty 20 | 21 | -- * Basic interface 22 | , Data.Text.cons 23 | , Data.Text.snoc 24 | , Data.Text.append 25 | , Data.Text.uncons 26 | , Data.Text.null 27 | , Data.Text.length 28 | , Data.Text.compareLength 29 | 30 | -- * Transformations 31 | , Data.Text.map 32 | , Data.Text.intercalate 33 | , Data.Text.intersperse 34 | , Data.Text.transpose 35 | , Data.Text.reverse 36 | 37 | -- ** Case conversion 38 | , Data.Text.toCaseFold 39 | , Data.Text.toLower 40 | , Data.Text.toUpper 41 | , Data.Text.toTitle 42 | 43 | -- ** Justification 44 | , Data.Text.justifyLeft 45 | , Data.Text.justifyRight 46 | , Data.Text.center 47 | 48 | -- * Folds 49 | , Data.Text.foldl 50 | , Data.Text.foldl' 51 | , Data.Text.foldr 52 | 53 | -- ** Special folds 54 | , Data.Text.concat 55 | , Data.Text.concatMap 56 | , Data.Text.any 57 | , Data.Text.all 58 | 59 | -- * Construction 60 | 61 | -- ** Scans 62 | , Data.Text.scanl 63 | , Data.Text.scanl1 -- scanl1 and scanr1 are /not/ partial 64 | , Data.Text.scanr 65 | , Data.Text.scanr1 66 | 67 | -- ** Accumulating maps 68 | , Data.Text.mapAccumL 69 | , Data.Text.mapAccumR 70 | 71 | -- ** Generation and unfolding 72 | , Data.Text.replicate 73 | , Data.Text.unfoldr 74 | , Data.Text.unfoldrN 75 | 76 | -- * Substrings 77 | 78 | -- ** Breaking strings 79 | , Data.Text.take 80 | , Data.Text.takeEnd 81 | , Data.Text.drop 82 | , Data.Text.dropEnd 83 | , Data.Text.takeWhile 84 | , Data.Text.takeWhileEnd 85 | , Data.Text.dropWhile 86 | , Data.Text.dropWhileEnd 87 | , Data.Text.dropAround 88 | , Data.Text.strip 89 | , Data.Text.stripStart 90 | , Data.Text.stripEnd 91 | , Data.Text.splitAt 92 | , Data.Text.break 93 | , Data.Text.span 94 | , Data.Text.group 95 | , Data.Text.groupBy 96 | , Data.Text.inits 97 | , Data.Text.tails 98 | 99 | -- ** Breaking into many substrings 100 | , Data.Text.split 101 | , Data.Text.chunksOf 102 | 103 | -- ** Breaking into lines and words 104 | , Data.Text.lines 105 | , linesCR 106 | , Data.Text.words 107 | , Data.Text.unlines 108 | , Data.Text.unwords 109 | 110 | -- * Predicates 111 | , Data.Text.isPrefixOf 112 | , Data.Text.isSuffixOf 113 | , Data.Text.isInfixOf 114 | 115 | -- ** View patterns 116 | , Data.Text.stripPrefix 117 | , Data.Text.stripSuffix 118 | , dropPrefix 119 | , dropSuffix 120 | , Data.Text.commonPrefixes 121 | 122 | -- * Searching 123 | , Data.Text.filter 124 | , Data.Text.find 125 | , Data.Text.partition 126 | 127 | -- * Indexing 128 | , Data.Text.index 129 | , Data.Text.findIndex 130 | 131 | -- * Zipping 132 | , Data.Text.zip 133 | , Data.Text.zipWith 134 | 135 | -- * Low level operations 136 | , Data.Text.copy 137 | , Data.Text.unpackCString# 138 | 139 | -- * Encoding 140 | , Data.Text.Encoding.encodeUtf8 141 | , Data.Text.Encoding.decodeUtf8With 142 | , Data.Text.Encoding.decodeUtf8' 143 | , Data.Text.Encoding.Error.lenientDecode 144 | ) where 145 | 146 | import Data.Maybe (fromMaybe) 147 | import Data.Text (Text, stripPrefix, stripSuffix) 148 | import qualified Data.Text 149 | import qualified Data.Text.Encoding 150 | import qualified Data.Text.Encoding.Error 151 | 152 | -- | Drop prefix if present, otherwise return original 'Text'. 153 | -- 154 | -- @since 0.0.0.0 155 | dropPrefix :: Text -- ^ prefix 156 | -> Text 157 | -> Text 158 | dropPrefix prefix t = fromMaybe t (stripPrefix prefix t) 159 | 160 | -- | Drop prefix if present, otherwise return original 'Text'. 161 | -- 162 | -- @since 0.0.0.0 163 | dropSuffix :: Text -- ^ suffix 164 | -> Text 165 | -> Text 166 | dropSuffix suffix t = fromMaybe t (stripSuffix suffix t) 167 | 168 | -- | 'linesCR' breaks a 'Text' up into a list of `Text`s at newline 169 | -- 'Char's. It is very similar to 'Data.Text.lines', but it also removes 170 | -- any trailing @'\r'@ characters. The resulting 'Text' values do not 171 | -- contain newlines or trailing @'\r'@ characters. 172 | -- 173 | -- @since 0.1.0.0 174 | linesCR :: Text -> [Text] 175 | linesCR = map (dropSuffix "\r") . Data.Text.lines 176 | -------------------------------------------------------------------------------- /rio/src/RIO/Text/Lazy.hs: -------------------------------------------------------------------------------- 1 | -- | Lazy @Text@. Import as: 2 | -- 3 | -- > import qualified RIO.Text.Lazy as TL 4 | -- 5 | -- This module does not export any partial functions. For those, see 6 | -- "RIO.Text.Lazy.Partial" 7 | module RIO.Text.Lazy 8 | ( 9 | -- * Types 10 | Data.Text.Lazy.Text 11 | 12 | -- * Creation and elimination 13 | , Data.Text.Lazy.pack 14 | , Data.Text.Lazy.unpack 15 | , Data.Text.Lazy.singleton 16 | , Data.Text.Lazy.empty 17 | , Data.Text.Lazy.fromChunks 18 | , Data.Text.Lazy.toChunks 19 | , Data.Text.Lazy.toStrict 20 | , Data.Text.Lazy.fromStrict 21 | , Data.Text.Lazy.foldrChunks 22 | , Data.Text.Lazy.foldlChunks 23 | 24 | -- * Basic interface 25 | , Data.Text.Lazy.cons 26 | , Data.Text.Lazy.snoc 27 | , Data.Text.Lazy.append 28 | , Data.Text.Lazy.uncons 29 | , Data.Text.Lazy.null 30 | , Data.Text.Lazy.length 31 | , Data.Text.Lazy.compareLength 32 | 33 | -- * Transformations 34 | , Data.Text.Lazy.map 35 | , Data.Text.Lazy.intercalate 36 | , Data.Text.Lazy.intersperse 37 | , Data.Text.Lazy.transpose 38 | , Data.Text.Lazy.reverse 39 | 40 | -- ** Case conversion 41 | , Data.Text.Lazy.toCaseFold 42 | , Data.Text.Lazy.toLower 43 | , Data.Text.Lazy.toUpper 44 | , Data.Text.Lazy.toTitle 45 | 46 | -- ** Justification 47 | , Data.Text.Lazy.justifyLeft 48 | , Data.Text.Lazy.justifyRight 49 | , Data.Text.Lazy.center 50 | 51 | -- * Folds 52 | , Data.Text.Lazy.foldl 53 | , Data.Text.Lazy.foldl' 54 | , Data.Text.Lazy.foldr 55 | 56 | -- ** Special folds 57 | , Data.Text.Lazy.concat 58 | , Data.Text.Lazy.concatMap 59 | , Data.Text.Lazy.any 60 | , Data.Text.Lazy.all 61 | 62 | -- * Construction 63 | 64 | -- ** Scans 65 | , Data.Text.Lazy.scanl 66 | , Data.Text.Lazy.scanl1 -- NB. scanl1 and scanr1 are not partial 67 | , Data.Text.Lazy.scanr 68 | , Data.Text.Lazy.scanr1 69 | 70 | -- ** Accumulating maps 71 | , Data.Text.Lazy.mapAccumL 72 | , Data.Text.Lazy.mapAccumR 73 | 74 | -- ** Generation and unfolding 75 | , Data.Text.Lazy.repeat 76 | , Data.Text.Lazy.replicate 77 | , Data.Text.Lazy.cycle 78 | , Data.Text.Lazy.iterate 79 | , Data.Text.Lazy.unfoldr 80 | , Data.Text.Lazy.unfoldrN 81 | 82 | -- * Substrings 83 | 84 | -- ** Breaking strings 85 | , Data.Text.Lazy.take 86 | , Data.Text.Lazy.takeEnd 87 | , Data.Text.Lazy.drop 88 | , Data.Text.Lazy.dropEnd 89 | , Data.Text.Lazy.takeWhile 90 | , Data.Text.Lazy.takeWhileEnd 91 | , Data.Text.Lazy.dropWhile 92 | , Data.Text.Lazy.dropWhileEnd 93 | , Data.Text.Lazy.dropAround 94 | , Data.Text.Lazy.strip 95 | , Data.Text.Lazy.stripStart 96 | , Data.Text.Lazy.stripEnd 97 | , Data.Text.Lazy.splitAt 98 | , Data.Text.Lazy.span 99 | , Data.Text.Lazy.break 100 | , Data.Text.Lazy.group 101 | , Data.Text.Lazy.groupBy 102 | , Data.Text.Lazy.inits 103 | , Data.Text.Lazy.tails 104 | 105 | -- ** Breaking into many substrings 106 | , Data.Text.Lazy.split 107 | , Data.Text.Lazy.chunksOf 108 | 109 | -- ** Breaking into lines and words 110 | , Data.Text.Lazy.lines 111 | , Data.Text.Lazy.words 112 | , Data.Text.Lazy.unlines 113 | , Data.Text.Lazy.unwords 114 | 115 | -- * Predicates 116 | , Data.Text.Lazy.isPrefixOf 117 | , Data.Text.Lazy.isSuffixOf 118 | , Data.Text.Lazy.isInfixOf 119 | 120 | -- ** View patterns 121 | , Data.Text.Lazy.stripPrefix 122 | , Data.Text.Lazy.stripSuffix 123 | , Data.Text.Lazy.commonPrefixes 124 | 125 | -- * Searching 126 | , Data.Text.Lazy.filter 127 | , Data.Text.Lazy.find 128 | , Data.Text.Lazy.partition 129 | 130 | -- * Indexing 131 | , Data.Text.Lazy.index 132 | , Data.Text.Lazy.count 133 | 134 | -- * Zipping and unzipping 135 | , Data.Text.Lazy.zip 136 | , Data.Text.Lazy.zipWith 137 | ) where 138 | 139 | import qualified Data.Text.Lazy 140 | -------------------------------------------------------------------------------- /rio/src/RIO/Text/Lazy/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Lazy @Text@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Text.Lazy.Partial as TL' 4 | module RIO.Text.Lazy.Partial 5 | ( 6 | -- * Creation and elimination 7 | Data.Text.Lazy.head 8 | , Data.Text.Lazy.last 9 | , Data.Text.Lazy.tail 10 | , Data.Text.Lazy.init 11 | 12 | -- * Transformations 13 | , Data.Text.Lazy.replace 14 | 15 | -- * Folds 16 | , Data.Text.Lazy.foldl1 17 | , Data.Text.Lazy.foldl1' 18 | , Data.Text.Lazy.foldr1 19 | 20 | -- ** Special folds 21 | , Data.Text.Lazy.maximum 22 | , Data.Text.Lazy.minimum 23 | 24 | -- * Substrings 25 | 26 | -- ** Breaking strings 27 | , Data.Text.Lazy.breakOn 28 | , Data.Text.Lazy.breakOnEnd 29 | 30 | -- ** Breaking into many substrings 31 | , Data.Text.Lazy.splitOn 32 | 33 | -- * Searching 34 | , Data.Text.Lazy.breakOnAll 35 | ) where 36 | 37 | import qualified Data.Text.Lazy 38 | -------------------------------------------------------------------------------- /rio/src/RIO/Text/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Strict @Text@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Text.Partial as T' 4 | module RIO.Text.Partial 5 | ( 6 | -- * Basic interface 7 | Data.Text.head 8 | , Data.Text.last 9 | , Data.Text.tail 10 | , Data.Text.init 11 | 12 | -- * Transformations 13 | , Data.Text.replace 14 | 15 | -- * Folds 16 | , Data.Text.foldl1 17 | , Data.Text.foldl1' 18 | , Data.Text.foldr1 19 | 20 | -- ** Special folds 21 | , Data.Text.maximum 22 | , Data.Text.minimum 23 | 24 | -- * Substrings 25 | 26 | -- ** Breaking strings 27 | , Data.Text.breakOn 28 | , Data.Text.breakOnEnd 29 | 30 | -- ** Breaking into many substrings 31 | , Data.Text.splitOn 32 | 33 | -- * Searching 34 | , Data.Text.breakOnAll 35 | 36 | -- * Indexing 37 | , Data.Text.count 38 | ) where 39 | 40 | import qualified Data.Text 41 | -------------------------------------------------------------------------------- /rio/src/RIO/Time.hs: -------------------------------------------------------------------------------- 1 | module RIO.Time 2 | ( module Data.Time 3 | , getCurrentTime 4 | , getTimeZone 5 | , getCurrentTimeZone 6 | , getZonedTime 7 | , utcToLocalZonedTime 8 | ) where 9 | 10 | import Control.Monad.IO.Class 11 | import Data.Time hiding( getCurrentTime, getTimeZone, getCurrentTimeZone 12 | , getZonedTime, utcToLocalZonedTime) 13 | import qualified Data.Time 14 | 15 | getCurrentTime :: MonadIO m => m UTCTime 16 | getCurrentTime = liftIO Data.Time.getCurrentTime 17 | 18 | getTimeZone :: MonadIO m => UTCTime -> m TimeZone 19 | getTimeZone = liftIO . Data.Time.getTimeZone 20 | 21 | getCurrentTimeZone :: MonadIO m => m TimeZone 22 | getCurrentTimeZone = liftIO Data.Time.getCurrentTimeZone 23 | 24 | getZonedTime :: MonadIO m => m ZonedTime 25 | getZonedTime = liftIO Data.Time.getZonedTime 26 | 27 | utcToLocalZonedTime :: MonadIO m => UTCTime -> m ZonedTime 28 | utcToLocalZonedTime = liftIO . Data.Time.utcToLocalZonedTime 29 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | 3 | -- | Generic @Vector@ interface. Import as: 4 | -- 5 | -- > import qualified RIO.Vector as V 6 | -- 7 | -- This module does not export any partial or unsafe functions. For those, see 8 | -- "RIO.Vector.Partial" and "RIO.Vector.Unsafe" 9 | module RIO.Vector 10 | ( 11 | -- * Immutable vectors 12 | Data.Vector.Generic.Vector 13 | 14 | -- * Accessors 15 | -- ** Length information 16 | , Data.Vector.Generic.length 17 | , Data.Vector.Generic.null 18 | 19 | -- ** Indexing 20 | , (Data.Vector.Generic.!?) 21 | 22 | -- ** Extracting subvectors 23 | , Data.Vector.Generic.slice 24 | , Data.Vector.Generic.take 25 | , Data.Vector.Generic.drop 26 | , Data.Vector.Generic.splitAt 27 | 28 | -- * Construction 29 | -- ** Initialisation 30 | , Data.Vector.Generic.empty 31 | , Data.Vector.Generic.singleton 32 | , Data.Vector.Generic.replicate 33 | , Data.Vector.Generic.generate 34 | , Data.Vector.Generic.iterateN 35 | 36 | -- ** Monadic initialisation 37 | , Data.Vector.Generic.replicateM 38 | , Data.Vector.Generic.generateM 39 | #if MIN_VERSION_vector(0,12,0) 40 | , Data.Vector.Generic.iterateNM 41 | #endif 42 | , Data.Vector.Generic.create 43 | #if MIN_VERSION_vector(0,12,0) 44 | , Data.Vector.Generic.createT 45 | #endif 46 | 47 | -- ** Unfolding 48 | , Data.Vector.Generic.unfoldr 49 | , Data.Vector.Generic.unfoldrN 50 | #if MIN_VERSION_vector(0,12,0) 51 | , Data.Vector.Generic.unfoldrM 52 | , Data.Vector.Generic.unfoldrNM 53 | #endif 54 | , Data.Vector.Generic.constructN 55 | , Data.Vector.Generic.constructrN 56 | 57 | -- ** Enumeration 58 | , Data.Vector.Generic.enumFromN 59 | , Data.Vector.Generic.enumFromStepN 60 | , Data.Vector.Generic.enumFromTo 61 | , Data.Vector.Generic.enumFromThenTo 62 | 63 | -- ** Concatenation 64 | , Data.Vector.Generic.cons 65 | , Data.Vector.Generic.snoc 66 | , (Data.Vector.Generic.++) 67 | , Data.Vector.Generic.concat 68 | #if MIN_VERSION_vector(0,12,0) 69 | , Data.Vector.Generic.concatNE 70 | #endif 71 | 72 | -- ** Restricting memory usage 73 | , Data.Vector.Generic.force 74 | 75 | -- * Modifying vectors 76 | -- ** Permutations 77 | , Data.Vector.Generic.reverse 78 | 79 | -- ** Safe destructive update 80 | , Data.Vector.Generic.modify 81 | 82 | -- * Elementwise operations 83 | -- ** Indexing 84 | , Data.Vector.Generic.indexed 85 | 86 | -- ** Mapping 87 | , Data.Vector.Generic.map 88 | , Data.Vector.Generic.imap 89 | , Data.Vector.Generic.concatMap 90 | 91 | -- ** Monadic mapping 92 | , Data.Vector.Generic.mapM 93 | , Data.Vector.Generic.imapM 94 | , Data.Vector.Generic.mapM_ 95 | , Data.Vector.Generic.imapM_ 96 | , Data.Vector.Generic.forM 97 | , Data.Vector.Generic.forM_ 98 | 99 | -- ** Zipping 100 | , Data.Vector.Generic.zipWith 101 | , Data.Vector.Generic.zipWith3 102 | , Data.Vector.Generic.zipWith4 103 | , Data.Vector.Generic.zipWith5 104 | , Data.Vector.Generic.zipWith6 105 | , Data.Vector.Generic.izipWith 106 | , Data.Vector.Generic.izipWith3 107 | , Data.Vector.Generic.izipWith4 108 | , Data.Vector.Generic.izipWith5 109 | , Data.Vector.Generic.izipWith6 110 | , Data.Vector.Generic.zip 111 | , Data.Vector.Generic.zip3 112 | , Data.Vector.Generic.zip4 113 | , Data.Vector.Generic.zip5 114 | , Data.Vector.Generic.zip6 115 | 116 | -- ** Monadic zipping 117 | , Data.Vector.Generic.zipWithM 118 | , Data.Vector.Generic.izipWithM 119 | , Data.Vector.Generic.zipWithM_ 120 | , Data.Vector.Generic.izipWithM_ 121 | 122 | -- ** Unzipping 123 | , Data.Vector.Generic.unzip 124 | , Data.Vector.Generic.unzip3 125 | , Data.Vector.Generic.unzip4 126 | , Data.Vector.Generic.unzip5 127 | , Data.Vector.Generic.unzip6 128 | 129 | -- * Working with predicates 130 | -- ** Filtering 131 | , Data.Vector.Generic.filter 132 | , Data.Vector.Generic.ifilter 133 | #if MIN_VERSION_vector(0,12,0) 134 | , Data.Vector.Generic.uniq 135 | , Data.Vector.Generic.mapMaybe 136 | , Data.Vector.Generic.imapMaybe 137 | #endif 138 | , Data.Vector.Generic.filterM 139 | , Data.Vector.Generic.takeWhile 140 | , Data.Vector.Generic.dropWhile 141 | 142 | -- ** Partitioning 143 | , Data.Vector.Generic.partition 144 | , Data.Vector.Generic.unstablePartition 145 | , Data.Vector.Generic.span 146 | , Data.Vector.Generic.break 147 | 148 | -- ** Searching 149 | , Data.Vector.Generic.elem 150 | , Data.Vector.Generic.notElem 151 | , Data.Vector.Generic.find 152 | , Data.Vector.Generic.findIndex 153 | , Data.Vector.Generic.findIndices 154 | , Data.Vector.Generic.elemIndex 155 | , Data.Vector.Generic.elemIndices 156 | 157 | -- * Folding 158 | , Data.Vector.Generic.foldl 159 | , Data.Vector.Generic.foldl' 160 | , Data.Vector.Generic.foldr 161 | , Data.Vector.Generic.foldr' 162 | , Data.Vector.Generic.ifoldl 163 | , Data.Vector.Generic.ifoldl' 164 | , Data.Vector.Generic.ifoldr 165 | , Data.Vector.Generic.ifoldr' 166 | 167 | -- ** Specialised folds 168 | , Data.Vector.Generic.all 169 | , Data.Vector.Generic.any 170 | , Data.Vector.Generic.and 171 | , Data.Vector.Generic.or 172 | , Data.Vector.Generic.sum 173 | , Data.Vector.Generic.product 174 | 175 | -- ** Monadic folds 176 | , Data.Vector.Generic.foldM 177 | , Data.Vector.Generic.ifoldM 178 | , Data.Vector.Generic.foldM' 179 | , Data.Vector.Generic.ifoldM' 180 | , Data.Vector.Generic.foldM_ 181 | , Data.Vector.Generic.ifoldM_ 182 | , Data.Vector.Generic.foldM'_ 183 | , Data.Vector.Generic.ifoldM'_ 184 | 185 | -- ** Monadic sequencing 186 | , Data.Vector.Generic.sequence 187 | , Data.Vector.Generic.sequence_ 188 | 189 | -- * Prefix sums (scans) 190 | , Data.Vector.Generic.prescanl 191 | , Data.Vector.Generic.prescanl' 192 | , Data.Vector.Generic.postscanl 193 | , Data.Vector.Generic.postscanl' 194 | , Data.Vector.Generic.scanl 195 | , Data.Vector.Generic.scanl' 196 | #if MIN_VERSION_vector(0,12,0) 197 | , Data.Vector.Generic.iscanl 198 | , Data.Vector.Generic.iscanl' 199 | #endif 200 | , Data.Vector.Generic.prescanr 201 | , Data.Vector.Generic.prescanr' 202 | , Data.Vector.Generic.postscanr 203 | , Data.Vector.Generic.postscanr' 204 | , Data.Vector.Generic.scanr 205 | , Data.Vector.Generic.scanr' 206 | #if MIN_VERSION_vector(0,12,0) 207 | , Data.Vector.Generic.iscanr 208 | , Data.Vector.Generic.iscanr' 209 | #endif 210 | 211 | -- * Conversions 212 | -- ** Lists 213 | , Data.Vector.Generic.toList 214 | , Data.Vector.Generic.fromList 215 | , Data.Vector.Generic.fromListN 216 | 217 | -- ** Different vector types 218 | , Data.Vector.Generic.convert 219 | 220 | -- ** Mutable vectors 221 | , Data.Vector.Generic.freeze 222 | , Data.Vector.Generic.thaw 223 | , Data.Vector.Generic.copy 224 | 225 | -- * Fusion support 226 | -- ** Conversion to/from Bundles 227 | , Data.Vector.Generic.stream 228 | , Data.Vector.Generic.unstream 229 | , Data.Vector.Generic.streamR 230 | , Data.Vector.Generic.unstreamR 231 | 232 | -- ** Recycling support 233 | , Data.Vector.Generic.new 234 | , Data.Vector.Generic.clone 235 | 236 | -- * Utilities 237 | -- ** Comparisons 238 | , Data.Vector.Generic.eq 239 | , Data.Vector.Generic.cmp 240 | #if MIN_VERSION_vector(0,12,0) 241 | , Data.Vector.Generic.eqBy 242 | , Data.Vector.Generic.cmpBy 243 | #endif 244 | 245 | -- ** Show and Read 246 | , Data.Vector.Generic.showsPrec 247 | , Data.Vector.Generic.readPrec 248 | #if MIN_VERSION_vector(0,12,0) 249 | , Data.Vector.Generic.liftShowsPrec 250 | , Data.Vector.Generic.liftReadsPrec 251 | #endif 252 | 253 | -- ** @Data@ and @Typeable@ 254 | , Data.Vector.Generic.gfoldl 255 | , Data.Vector.Generic.dataCast 256 | , Data.Vector.Generic.mkType 257 | ) where 258 | 259 | import qualified Data.Vector.Generic 260 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Boxed.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | 3 | -- | Boxed @Vector@. Import as: 4 | -- 5 | -- > import qualified RIO.Vector.Boxed as VB 6 | -- 7 | -- This module does not export any partial or unsafe functions. For those, see 8 | -- "RIO.Vector.Boxed.Partial" and "RIO.Vector.Boxed.Unsafe" 9 | module RIO.Vector.Boxed 10 | ( 11 | -- * Boxed vectors 12 | Data.Vector.Vector 13 | , Data.Vector.MVector 14 | 15 | -- * Accessors 16 | -- ** Length information 17 | , Data.Vector.length 18 | , Data.Vector.null 19 | 20 | -- ** Indexing 21 | , (Data.Vector.!?) 22 | 23 | -- ** Extracting subvectors 24 | , Data.Vector.slice 25 | , Data.Vector.take 26 | , Data.Vector.drop 27 | , Data.Vector.splitAt 28 | 29 | -- * Construction 30 | -- ** Initialisation 31 | , Data.Vector.empty 32 | , Data.Vector.singleton 33 | , Data.Vector.replicate 34 | , Data.Vector.generate 35 | , Data.Vector.iterateN 36 | 37 | -- ** Monadic initialisation 38 | , Data.Vector.replicateM 39 | , Data.Vector.generateM 40 | #if MIN_VERSION_vector(0,12,0) 41 | , Data.Vector.iterateNM 42 | #endif 43 | , Data.Vector.create 44 | #if MIN_VERSION_vector(0,12,0) 45 | , Data.Vector.createT 46 | #endif 47 | 48 | -- ** Unfolding 49 | , Data.Vector.unfoldr 50 | , Data.Vector.unfoldrN 51 | #if MIN_VERSION_vector(0,12,0) 52 | , Data.Vector.unfoldrM 53 | , Data.Vector.unfoldrNM 54 | #endif 55 | , Data.Vector.constructN 56 | , Data.Vector.constructrN 57 | 58 | -- ** Enumeration 59 | , Data.Vector.enumFromN 60 | , Data.Vector.enumFromStepN 61 | , Data.Vector.enumFromTo 62 | , Data.Vector.enumFromThenTo 63 | 64 | -- ** Concatenation 65 | , Data.Vector.cons 66 | , Data.Vector.snoc 67 | , (Data.Vector.++) 68 | , Data.Vector.concat 69 | 70 | -- ** Restricting memory usage 71 | , Data.Vector.force 72 | 73 | -- * Modifying vectors 74 | -- ** Permutations 75 | , Data.Vector.reverse 76 | 77 | -- ** Safe destructive update 78 | , Data.Vector.modify 79 | 80 | -- * Elementwise operations 81 | -- ** Indexing 82 | , Data.Vector.indexed 83 | 84 | -- ** Mapping 85 | , Data.Vector.map 86 | , Data.Vector.imap 87 | , Data.Vector.concatMap 88 | 89 | -- ** Monadic mapping 90 | , Data.Vector.mapM 91 | , Data.Vector.imapM 92 | , Data.Vector.mapM_ 93 | , Data.Vector.imapM_ 94 | , Data.Vector.forM 95 | , Data.Vector.forM_ 96 | 97 | -- ** Zipping 98 | , Data.Vector.zipWith 99 | , Data.Vector.zipWith3 100 | , Data.Vector.zipWith4 101 | , Data.Vector.zipWith5 102 | , Data.Vector.zipWith6 103 | , Data.Vector.izipWith 104 | , Data.Vector.izipWith3 105 | , Data.Vector.izipWith4 106 | , Data.Vector.izipWith5 107 | , Data.Vector.izipWith6 108 | , Data.Vector.zip 109 | , Data.Vector.zip3 110 | , Data.Vector.zip4 111 | , Data.Vector.zip5 112 | , Data.Vector.zip6 113 | 114 | -- ** Monadic zipping 115 | , Data.Vector.zipWithM 116 | , Data.Vector.izipWithM 117 | , Data.Vector.zipWithM_ 118 | , Data.Vector.izipWithM_ 119 | 120 | -- ** Unzipping 121 | , Data.Vector.unzip 122 | , Data.Vector.unzip3 123 | , Data.Vector.unzip4 124 | , Data.Vector.unzip5 125 | , Data.Vector.unzip6 126 | 127 | -- * Working with predicates 128 | -- ** Filtering 129 | , Data.Vector.filter 130 | , Data.Vector.ifilter 131 | #if MIN_VERSION_vector(0,12,0) 132 | , Data.Vector.uniq 133 | , Data.Vector.mapMaybe 134 | , Data.Vector.imapMaybe 135 | #endif 136 | , Data.Vector.filterM 137 | , Data.Vector.takeWhile 138 | , Data.Vector.dropWhile 139 | 140 | -- ** Partitioning 141 | , Data.Vector.partition 142 | , Data.Vector.unstablePartition 143 | , Data.Vector.span 144 | , Data.Vector.break 145 | 146 | -- ** Searching 147 | , Data.Vector.elem 148 | , Data.Vector.notElem 149 | , Data.Vector.find 150 | , Data.Vector.findIndex 151 | , Data.Vector.findIndices 152 | , Data.Vector.elemIndex 153 | , Data.Vector.elemIndices 154 | 155 | -- * Folding 156 | , Data.Vector.foldl 157 | , Data.Vector.foldl' 158 | , Data.Vector.foldr 159 | , Data.Vector.foldr' 160 | , Data.Vector.ifoldl 161 | , Data.Vector.ifoldl' 162 | , Data.Vector.ifoldr 163 | , Data.Vector.ifoldr' 164 | 165 | -- ** Specialised folds 166 | , Data.Vector.all 167 | , Data.Vector.any 168 | , Data.Vector.and 169 | , Data.Vector.or 170 | , Data.Vector.sum 171 | , Data.Vector.product 172 | 173 | -- ** Monadic folds 174 | , Data.Vector.foldM 175 | , Data.Vector.ifoldM 176 | , Data.Vector.foldM' 177 | , Data.Vector.ifoldM' 178 | , Data.Vector.foldM_ 179 | , Data.Vector.ifoldM_ 180 | , Data.Vector.foldM'_ 181 | , Data.Vector.ifoldM'_ 182 | 183 | -- ** Monadic sequencing 184 | , Data.Vector.sequence 185 | , Data.Vector.sequence_ 186 | 187 | -- * Prefix sums (scans) 188 | , Data.Vector.prescanl 189 | , Data.Vector.prescanl' 190 | , Data.Vector.postscanl 191 | , Data.Vector.postscanl' 192 | , Data.Vector.scanl 193 | , Data.Vector.scanl' 194 | #if MIN_VERSION_vector(0,12,0) 195 | , Data.Vector.iscanl 196 | , Data.Vector.iscanl' 197 | #endif 198 | , Data.Vector.prescanr 199 | , Data.Vector.prescanr' 200 | , Data.Vector.postscanr 201 | , Data.Vector.postscanr' 202 | , Data.Vector.scanr 203 | , Data.Vector.scanr' 204 | #if MIN_VERSION_vector(0,12,0) 205 | , Data.Vector.iscanr 206 | , Data.Vector.iscanr' 207 | #endif 208 | 209 | -- * Conversions 210 | -- ** Lists 211 | , Data.Vector.toList 212 | , Data.Vector.fromList 213 | , Data.Vector.fromListN 214 | 215 | -- ** Different vector types 216 | , Data.Vector.convert 217 | 218 | -- ** Mutable vectors 219 | , Data.Vector.freeze 220 | , Data.Vector.thaw 221 | , Data.Vector.copy 222 | ) where 223 | 224 | import qualified Data.Vector 225 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Boxed/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Boxed @Vector@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Vector.Boxed.Partial as VB' 4 | module RIO.Vector.Boxed.Partial 5 | ( 6 | -- * Accessors 7 | -- ** Indexing 8 | (Data.Vector.!) 9 | , Data.Vector.head 10 | , Data.Vector.last 11 | 12 | -- ** Monadic indexing 13 | , Data.Vector.indexM 14 | , Data.Vector.headM 15 | , Data.Vector.lastM 16 | 17 | -- ** Extracting subvectors 18 | , Data.Vector.init 19 | , Data.Vector.tail 20 | 21 | -- * Modifying vectors 22 | -- ** Bulk updates 23 | , (Data.Vector.//) 24 | , Data.Vector.update 25 | , Data.Vector.update_ 26 | 27 | -- ** Accumulations 28 | , Data.Vector.accum 29 | , Data.Vector.accumulate 30 | , Data.Vector.accumulate_ 31 | 32 | -- ** Permutations 33 | , Data.Vector.backpermute 34 | 35 | -- * Folding 36 | , Data.Vector.foldl1 37 | , Data.Vector.foldl1' 38 | , Data.Vector.foldr1 39 | , Data.Vector.foldr1' 40 | 41 | -- ** Specialised folds 42 | , Data.Vector.maximum 43 | , Data.Vector.maximumBy 44 | , Data.Vector.minimum 45 | , Data.Vector.minimumBy 46 | , Data.Vector.minIndex 47 | , Data.Vector.minIndexBy 48 | , Data.Vector.maxIndex 49 | , Data.Vector.maxIndexBy 50 | 51 | -- ** Monadic folds 52 | , Data.Vector.fold1M 53 | , Data.Vector.fold1M' 54 | , Data.Vector.fold1M_ 55 | , Data.Vector.fold1M'_ 56 | 57 | -- * Prefix sums (scans) 58 | , Data.Vector.scanl1 59 | , Data.Vector.scanl1' 60 | , Data.Vector.scanr1 61 | , Data.Vector.scanr1' 62 | ) where 63 | 64 | import qualified Data.Vector 65 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Boxed/Unsafe.hs: -------------------------------------------------------------------------------- 1 | -- | Boxed @Vector@ unsafe functions. These perform no bounds 2 | -- checking, and may cause segmentation faults etc.! Import as: 3 | -- 4 | -- > import qualified RIO.Vector.Boxed.Unsafe as VB' 5 | module RIO.Vector.Boxed.Unsafe 6 | ( 7 | -- * Accessors 8 | -- ** Indexing 9 | Data.Vector.unsafeIndex 10 | , Data.Vector.unsafeHead 11 | , Data.Vector.unsafeLast 12 | 13 | -- ** Monadic indexing 14 | , Data.Vector.unsafeIndexM 15 | , Data.Vector.unsafeHeadM 16 | , Data.Vector.unsafeLastM 17 | 18 | -- ** Extracting subvectors 19 | , Data.Vector.unsafeSlice 20 | , Data.Vector.unsafeInit 21 | , Data.Vector.unsafeTail 22 | , Data.Vector.unsafeTake 23 | , Data.Vector.unsafeDrop 24 | 25 | -- * Modifying vectors 26 | -- ** Bulk updates 27 | , Data.Vector.unsafeUpd 28 | , Data.Vector.unsafeUpdate 29 | , Data.Vector.unsafeUpdate_ 30 | 31 | -- ** Accumulations 32 | , Data.Vector.unsafeAccum 33 | , Data.Vector.unsafeAccumulate 34 | , Data.Vector.unsafeAccumulate_ 35 | 36 | -- ** Permutations 37 | , Data.Vector.unsafeBackpermute 38 | 39 | -- * Conversions 40 | -- ** Mutable vectors 41 | , Data.Vector.unsafeFreeze 42 | , Data.Vector.unsafeThaw 43 | , Data.Vector.unsafeCopy 44 | ) where 45 | 46 | import qualified Data.Vector 47 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Generic @Vector@ interface partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Vector.Partial as V' 4 | module RIO.Vector.Partial 5 | ( 6 | -- * Accessors 7 | -- ** Indexing 8 | (Data.Vector.Generic.!) 9 | , Data.Vector.Generic.head 10 | , Data.Vector.Generic.last 11 | 12 | -- ** Monadic indexing 13 | , Data.Vector.Generic.indexM 14 | , Data.Vector.Generic.headM 15 | , Data.Vector.Generic.lastM 16 | 17 | -- ** Extracting subvectors 18 | , Data.Vector.Generic.init 19 | , Data.Vector.Generic.tail 20 | 21 | -- * Modifying vectors 22 | -- ** Bulk updates 23 | , (Data.Vector.Generic.//) 24 | , Data.Vector.Generic.update 25 | , Data.Vector.Generic.update_ 26 | 27 | -- ** Accumulations 28 | , Data.Vector.Generic.accum 29 | , Data.Vector.Generic.accumulate 30 | , Data.Vector.Generic.accumulate_ 31 | 32 | -- ** Permutations 33 | , Data.Vector.Generic.backpermute 34 | 35 | -- * Folding 36 | , Data.Vector.Generic.foldl1 37 | , Data.Vector.Generic.foldl1' 38 | , Data.Vector.Generic.foldr1 39 | , Data.Vector.Generic.foldr1' 40 | 41 | -- ** Specialised folds 42 | , Data.Vector.Generic.maximum 43 | , Data.Vector.Generic.maximumBy 44 | , Data.Vector.Generic.minimum 45 | , Data.Vector.Generic.minimumBy 46 | , Data.Vector.Generic.minIndex 47 | , Data.Vector.Generic.minIndexBy 48 | , Data.Vector.Generic.maxIndex 49 | , Data.Vector.Generic.maxIndexBy 50 | 51 | -- ** Monadic folds 52 | , Data.Vector.Generic.fold1M 53 | , Data.Vector.Generic.fold1M' 54 | , Data.Vector.Generic.fold1M_ 55 | , Data.Vector.Generic.fold1M'_ 56 | 57 | -- * Prefix sums (scans) 58 | , Data.Vector.Generic.scanl1 59 | , Data.Vector.Generic.scanl1' 60 | , Data.Vector.Generic.scanr1 61 | , Data.Vector.Generic.scanr1' 62 | ) where 63 | 64 | import qualified Data.Vector.Generic 65 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Storable.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | 3 | -- | Storable @Vector@. Import as: 4 | -- 5 | -- > import qualified RIO.Vector.Storable as VS 6 | -- 7 | -- This module does not export any partial or unsafe functions. For those, see 8 | -- "RIO.Vector.Storable.Partial" and "RIO.Vector.Storable.Unsafe" 9 | module RIO.Vector.Storable 10 | ( 11 | -- * Storable vectors 12 | Data.Vector.Storable.Vector 13 | , Data.Vector.Storable.MVector(..) 14 | , Data.Vector.Storable.Storable 15 | 16 | -- * Accessors 17 | -- ** Length information 18 | , Data.Vector.Storable.length 19 | , Data.Vector.Storable.null 20 | 21 | -- ** Indexing 22 | , (Data.Vector.Storable.!?) 23 | 24 | -- ** Extracting subvectors 25 | , Data.Vector.Storable.slice 26 | , Data.Vector.Storable.take 27 | , Data.Vector.Storable.drop 28 | , Data.Vector.Storable.splitAt 29 | 30 | -- * Construction 31 | -- ** Initialisation 32 | , Data.Vector.Storable.empty 33 | , Data.Vector.Storable.singleton 34 | , Data.Vector.Storable.replicate 35 | , Data.Vector.Storable.generate 36 | , Data.Vector.Storable.iterateN 37 | 38 | -- ** Monadic initialisation 39 | , Data.Vector.Storable.replicateM 40 | , Data.Vector.Storable.generateM 41 | #if MIN_VERSION_vector(0,12,0) 42 | , Data.Vector.Storable.iterateNM 43 | #endif 44 | , Data.Vector.Storable.create 45 | #if MIN_VERSION_vector(0,12,0) 46 | , Data.Vector.Storable.createT 47 | #endif 48 | 49 | -- ** Unfolding 50 | , Data.Vector.Storable.unfoldr 51 | , Data.Vector.Storable.unfoldrN 52 | #if MIN_VERSION_vector(0,12,0) 53 | , Data.Vector.Storable.unfoldrM 54 | , Data.Vector.Storable.unfoldrNM 55 | #endif 56 | , Data.Vector.Storable.constructN 57 | , Data.Vector.Storable.constructrN 58 | 59 | -- ** Enumeration 60 | , Data.Vector.Storable.enumFromN 61 | , Data.Vector.Storable.enumFromStepN 62 | , Data.Vector.Storable.enumFromTo 63 | , Data.Vector.Storable.enumFromThenTo 64 | 65 | -- ** Concatenation 66 | , Data.Vector.Storable.cons 67 | , Data.Vector.Storable.snoc 68 | , (Data.Vector.Storable.++) 69 | , Data.Vector.Storable.concat 70 | 71 | -- ** Restricting memory usage 72 | , Data.Vector.Storable.force 73 | 74 | -- * Modifying vectors 75 | -- ** Permutations 76 | , Data.Vector.Storable.reverse 77 | 78 | -- ** Safe destructive update 79 | , Data.Vector.Storable.modify 80 | 81 | -- * Elementwise operations 82 | -- ** Mapping 83 | , Data.Vector.Storable.map 84 | , Data.Vector.Storable.imap 85 | , Data.Vector.Storable.concatMap 86 | 87 | -- ** Monadic mapping 88 | , Data.Vector.Storable.mapM 89 | , Data.Vector.Storable.mapM_ 90 | , Data.Vector.Storable.forM 91 | , Data.Vector.Storable.forM_ 92 | 93 | -- ** Zipping 94 | , Data.Vector.Storable.zipWith 95 | , Data.Vector.Storable.zipWith3 96 | , Data.Vector.Storable.zipWith4 97 | , Data.Vector.Storable.zipWith5 98 | , Data.Vector.Storable.zipWith6 99 | , Data.Vector.Storable.izipWith 100 | , Data.Vector.Storable.izipWith3 101 | , Data.Vector.Storable.izipWith4 102 | , Data.Vector.Storable.izipWith5 103 | , Data.Vector.Storable.izipWith6 104 | 105 | -- ** Monadic zipping 106 | , Data.Vector.Storable.zipWithM 107 | , Data.Vector.Storable.zipWithM_ 108 | 109 | -- * Working with predicates 110 | -- ** Filtering 111 | , Data.Vector.Storable.filter 112 | , Data.Vector.Storable.ifilter 113 | #if MIN_VERSION_vector(0,12,0) 114 | , Data.Vector.Storable.uniq 115 | , Data.Vector.Storable.mapMaybe 116 | , Data.Vector.Storable.imapMaybe 117 | #endif 118 | , Data.Vector.Storable.filterM 119 | , Data.Vector.Storable.takeWhile 120 | , Data.Vector.Storable.dropWhile 121 | 122 | -- ** Partitioning 123 | , Data.Vector.Storable.partition 124 | , Data.Vector.Storable.unstablePartition 125 | , Data.Vector.Storable.span 126 | , Data.Vector.Storable.break 127 | 128 | -- ** Searching 129 | , Data.Vector.Storable.elem 130 | , Data.Vector.Storable.notElem 131 | , Data.Vector.Storable.find 132 | , Data.Vector.Storable.findIndex 133 | , Data.Vector.Storable.findIndices 134 | , Data.Vector.Storable.elemIndex 135 | , Data.Vector.Storable.elemIndices 136 | 137 | -- * Folding 138 | , Data.Vector.Storable.foldl 139 | , Data.Vector.Storable.foldl' 140 | , Data.Vector.Storable.foldr 141 | , Data.Vector.Storable.foldr' 142 | , Data.Vector.Storable.ifoldl 143 | , Data.Vector.Storable.ifoldl' 144 | , Data.Vector.Storable.ifoldr 145 | , Data.Vector.Storable.ifoldr' 146 | 147 | -- ** Specialised folds 148 | , Data.Vector.Storable.all 149 | , Data.Vector.Storable.any 150 | , Data.Vector.Storable.and 151 | , Data.Vector.Storable.or 152 | , Data.Vector.Storable.sum 153 | , Data.Vector.Storable.product 154 | 155 | -- ** Monadic folds 156 | , Data.Vector.Storable.foldM 157 | , Data.Vector.Storable.foldM' 158 | , Data.Vector.Storable.foldM_ 159 | , Data.Vector.Storable.foldM'_ 160 | 161 | -- * Prefix sums (scans) 162 | , Data.Vector.Storable.prescanl 163 | , Data.Vector.Storable.prescanl' 164 | , Data.Vector.Storable.postscanl 165 | , Data.Vector.Storable.postscanl' 166 | , Data.Vector.Storable.scanl 167 | , Data.Vector.Storable.scanl' 168 | , Data.Vector.Storable.prescanr 169 | , Data.Vector.Storable.prescanr' 170 | , Data.Vector.Storable.postscanr 171 | , Data.Vector.Storable.postscanr' 172 | , Data.Vector.Storable.scanr 173 | , Data.Vector.Storable.scanr' 174 | 175 | -- * Conversions 176 | -- ** Lists 177 | , Data.Vector.Storable.toList 178 | , Data.Vector.Storable.fromList 179 | , Data.Vector.Storable.fromListN 180 | 181 | -- ** Different vector types 182 | , Data.Vector.Storable.convert 183 | 184 | -- ** Mutable vectors 185 | , Data.Vector.Storable.freeze 186 | , Data.Vector.Storable.thaw 187 | , Data.Vector.Storable.copy 188 | ) where 189 | 190 | import qualified Data.Vector.Storable 191 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Storable/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Storable @Vector@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Vector.Storable.Partial as VS' 4 | module RIO.Vector.Storable.Partial 5 | ( 6 | -- * Accessors 7 | -- ** Indexing 8 | (Data.Vector.Storable.!) 9 | , Data.Vector.Storable.head 10 | , Data.Vector.Storable.last 11 | 12 | -- ** Monadic indexing 13 | , Data.Vector.Storable.indexM 14 | , Data.Vector.Storable.headM 15 | , Data.Vector.Storable.lastM 16 | 17 | -- ** Extracting subvectors 18 | , Data.Vector.Storable.init 19 | , Data.Vector.Storable.tail 20 | 21 | -- * Modifying vectors 22 | -- ** Bulk updates 23 | , (Data.Vector.Storable.//) 24 | , Data.Vector.Storable.update_ 25 | 26 | -- ** Accumulations 27 | , Data.Vector.Storable.accum 28 | , Data.Vector.Storable.accumulate_ 29 | 30 | -- ** Permutations 31 | , Data.Vector.Storable.backpermute 32 | 33 | -- * Folding 34 | , Data.Vector.Storable.foldl1 35 | , Data.Vector.Storable.foldl1' 36 | , Data.Vector.Storable.foldr1 37 | , Data.Vector.Storable.foldr1' 38 | 39 | -- ** Specialised folds 40 | , Data.Vector.Storable.maximum 41 | , Data.Vector.Storable.maximumBy 42 | , Data.Vector.Storable.minimum 43 | , Data.Vector.Storable.minimumBy 44 | , Data.Vector.Storable.minIndex 45 | , Data.Vector.Storable.minIndexBy 46 | , Data.Vector.Storable.maxIndex 47 | , Data.Vector.Storable.maxIndexBy 48 | 49 | -- ** Monadic folds 50 | , Data.Vector.Storable.fold1M 51 | , Data.Vector.Storable.fold1M' 52 | , Data.Vector.Storable.fold1M_ 53 | , Data.Vector.Storable.fold1M'_ 54 | 55 | -- * Prefix sums (scans) 56 | , Data.Vector.Storable.scanl1 57 | , Data.Vector.Storable.scanl1' 58 | , Data.Vector.Storable.scanr1 59 | , Data.Vector.Storable.scanr1' 60 | ) where 61 | 62 | import qualified Data.Vector.Storable 63 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Storable/Unsafe.hs: -------------------------------------------------------------------------------- 1 | -- | Storable @Vector@ unsafe functions. These perform no bounds 2 | -- checking, and may cause segmentation faults etc.! Import as: 3 | -- 4 | -- > import qualified RIO.Vector.Storable.Unsafe as VS' 5 | module RIO.Vector.Storable.Unsafe 6 | ( 7 | -- * Accessors 8 | -- ** Indexing 9 | Data.Vector.Storable.unsafeIndex 10 | , Data.Vector.Storable.unsafeHead 11 | , Data.Vector.Storable.unsafeLast 12 | 13 | -- ** Monadic indexing 14 | , Data.Vector.Storable.unsafeIndexM 15 | , Data.Vector.Storable.unsafeHeadM 16 | , Data.Vector.Storable.unsafeLastM 17 | 18 | -- ** Extracting subvectors 19 | , Data.Vector.Storable.unsafeSlice 20 | , Data.Vector.Storable.unsafeInit 21 | , Data.Vector.Storable.unsafeTail 22 | , Data.Vector.Storable.unsafeTake 23 | , Data.Vector.Storable.unsafeDrop 24 | 25 | -- * Modifying vectors 26 | -- ** Bulk updates 27 | , Data.Vector.Storable.unsafeUpd 28 | , Data.Vector.Storable.unsafeUpdate_ 29 | 30 | -- ** Accumulations 31 | , Data.Vector.Storable.unsafeAccum 32 | , Data.Vector.Storable.unsafeAccumulate_ 33 | 34 | -- ** Permutations 35 | , Data.Vector.Storable.unsafeBackpermute 36 | 37 | -- * Conversions 38 | -- ** Mutable vectors 39 | , Data.Vector.Storable.unsafeFreeze 40 | , Data.Vector.Storable.unsafeThaw 41 | , Data.Vector.Storable.unsafeCopy 42 | 43 | -- * Raw pointers 44 | , Data.Vector.Storable.unsafeFromForeignPtr 45 | , Data.Vector.Storable.unsafeFromForeignPtr0 46 | , Data.Vector.Storable.unsafeToForeignPtr 47 | , Data.Vector.Storable.unsafeToForeignPtr0 48 | , unsafeWith 49 | ) where 50 | 51 | import Data.Vector.Storable(Storable, Vector) 52 | import qualified Data.Vector.Storable 53 | import Foreign.Ptr(Ptr) 54 | import UnliftIO 55 | 56 | -- | Lifted version of 'Data.Vector.Storable.unsafeWith' 57 | unsafeWith :: (MonadUnliftIO m, Storable a) => Vector a -> (Ptr a -> m b) -> m b 58 | unsafeWith vec action = withRunInIO $ \unlifter -> Data.Vector.Storable.unsafeWith vec (unlifter . action) 59 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Unboxed.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | 3 | -- | Unboxed @Vector@. Import as: 4 | -- 5 | -- > import qualified RIO.Vector.Unboxed as VU 6 | -- 7 | -- This module does not export any partial or unsafe functions. For those, see 8 | -- "RIO.Vector.Unboxed.Partial" and "RIO.Vector.Unboxed.Unsafe" 9 | module RIO.Vector.Unboxed 10 | ( 11 | -- * Unboxed vectors 12 | Data.Vector.Unboxed.Vector 13 | , Data.Vector.Unboxed.MVector(..) 14 | , Data.Vector.Unboxed.Unbox 15 | 16 | -- * Accessors 17 | -- ** Length information 18 | , Data.Vector.Unboxed.length 19 | , Data.Vector.Unboxed.null 20 | 21 | -- ** Indexing 22 | , (Data.Vector.Unboxed.!?) 23 | 24 | -- ** Extracting subvectors 25 | , Data.Vector.Unboxed.slice 26 | , Data.Vector.Unboxed.take 27 | , Data.Vector.Unboxed.drop 28 | , Data.Vector.Unboxed.splitAt 29 | 30 | -- * Construction 31 | -- ** Initialisation 32 | , Data.Vector.Unboxed.empty 33 | , Data.Vector.Unboxed.singleton 34 | , Data.Vector.Unboxed.replicate 35 | , Data.Vector.Unboxed.generate 36 | , Data.Vector.Unboxed.iterateN 37 | 38 | -- ** Monadic initialisation 39 | , Data.Vector.Unboxed.replicateM 40 | , Data.Vector.Unboxed.generateM 41 | #if MIN_VERSION_vector(0,12,0) 42 | , Data.Vector.Unboxed.iterateNM 43 | #endif 44 | , Data.Vector.Unboxed.create 45 | #if MIN_VERSION_vector(0,12,0) 46 | , Data.Vector.Unboxed.createT 47 | #endif 48 | 49 | -- ** Unfolding 50 | , Data.Vector.Unboxed.unfoldr 51 | , Data.Vector.Unboxed.unfoldrN 52 | #if MIN_VERSION_vector(0,12,0) 53 | , Data.Vector.Unboxed.unfoldrM 54 | , Data.Vector.Unboxed.unfoldrNM 55 | #endif 56 | , Data.Vector.Unboxed.constructN 57 | , Data.Vector.Unboxed.constructrN 58 | 59 | -- ** Enumeration 60 | , Data.Vector.Unboxed.enumFromN 61 | , Data.Vector.Unboxed.enumFromStepN 62 | , Data.Vector.Unboxed.enumFromTo 63 | , Data.Vector.Unboxed.enumFromThenTo 64 | 65 | -- ** Concatenation 66 | , Data.Vector.Unboxed.cons 67 | , Data.Vector.Unboxed.snoc 68 | , (Data.Vector.Unboxed.++) 69 | , Data.Vector.Unboxed.concat 70 | 71 | -- ** Restricting memory usage 72 | , Data.Vector.Unboxed.force 73 | 74 | -- * Modifying vectors 75 | -- ** Permutations 76 | , Data.Vector.Unboxed.reverse 77 | 78 | -- ** Safe destructive update 79 | , Data.Vector.Unboxed.modify 80 | 81 | -- * Elementwise operations 82 | -- ** Indexing 83 | , Data.Vector.Unboxed.indexed 84 | 85 | -- ** Mapping 86 | , Data.Vector.Unboxed.map 87 | , Data.Vector.Unboxed.imap 88 | , Data.Vector.Unboxed.concatMap 89 | 90 | -- ** Monadic mapping 91 | , Data.Vector.Unboxed.mapM 92 | , Data.Vector.Unboxed.imapM 93 | , Data.Vector.Unboxed.mapM_ 94 | , Data.Vector.Unboxed.imapM_ 95 | , Data.Vector.Unboxed.forM 96 | , Data.Vector.Unboxed.forM_ 97 | 98 | -- ** Zipping 99 | , Data.Vector.Unboxed.zipWith 100 | , Data.Vector.Unboxed.zipWith3 101 | , Data.Vector.Unboxed.zipWith4 102 | , Data.Vector.Unboxed.zipWith5 103 | , Data.Vector.Unboxed.zipWith6 104 | , Data.Vector.Unboxed.izipWith 105 | , Data.Vector.Unboxed.izipWith3 106 | , Data.Vector.Unboxed.izipWith4 107 | , Data.Vector.Unboxed.izipWith5 108 | , Data.Vector.Unboxed.izipWith6 109 | , Data.Vector.Unboxed.zip 110 | , Data.Vector.Unboxed.zip3 111 | , Data.Vector.Unboxed.zip4 112 | , Data.Vector.Unboxed.zip5 113 | , Data.Vector.Unboxed.zip6 114 | 115 | -- ** Monadic zipping 116 | , Data.Vector.Unboxed.zipWithM 117 | , Data.Vector.Unboxed.izipWithM 118 | , Data.Vector.Unboxed.zipWithM_ 119 | , Data.Vector.Unboxed.izipWithM_ 120 | 121 | -- ** Unzipping 122 | , Data.Vector.Unboxed.unzip 123 | , Data.Vector.Unboxed.unzip3 124 | , Data.Vector.Unboxed.unzip4 125 | , Data.Vector.Unboxed.unzip5 126 | , Data.Vector.Unboxed.unzip6 127 | 128 | -- * Working with predicates 129 | -- ** Filtering 130 | , Data.Vector.Unboxed.filter 131 | , Data.Vector.Unboxed.ifilter 132 | #if MIN_VERSION_vector(0,12,0) 133 | , Data.Vector.Unboxed.uniq 134 | , Data.Vector.Unboxed.mapMaybe 135 | , Data.Vector.Unboxed.imapMaybe 136 | #endif 137 | , Data.Vector.Unboxed.filterM 138 | , Data.Vector.Unboxed.takeWhile 139 | , Data.Vector.Unboxed.dropWhile 140 | 141 | -- ** Partitioning 142 | , Data.Vector.Unboxed.partition 143 | , Data.Vector.Unboxed.unstablePartition 144 | , Data.Vector.Unboxed.span 145 | , Data.Vector.Unboxed.break 146 | 147 | -- ** Searching 148 | , Data.Vector.Unboxed.elem 149 | , Data.Vector.Unboxed.notElem 150 | , Data.Vector.Unboxed.find 151 | , Data.Vector.Unboxed.findIndex 152 | , Data.Vector.Unboxed.findIndices 153 | , Data.Vector.Unboxed.elemIndex 154 | , Data.Vector.Unboxed.elemIndices 155 | 156 | -- * Folding 157 | , Data.Vector.Unboxed.foldl 158 | , Data.Vector.Unboxed.foldl' 159 | , Data.Vector.Unboxed.foldr 160 | , Data.Vector.Unboxed.foldr' 161 | , Data.Vector.Unboxed.ifoldl 162 | , Data.Vector.Unboxed.ifoldl' 163 | , Data.Vector.Unboxed.ifoldr 164 | , Data.Vector.Unboxed.ifoldr' 165 | 166 | -- ** Specialised folds 167 | , Data.Vector.Unboxed.all 168 | , Data.Vector.Unboxed.any 169 | , Data.Vector.Unboxed.and 170 | , Data.Vector.Unboxed.or 171 | , Data.Vector.Unboxed.sum 172 | , Data.Vector.Unboxed.product 173 | 174 | -- ** Monadic folds 175 | , Data.Vector.Unboxed.foldM 176 | , Data.Vector.Unboxed.ifoldM 177 | , Data.Vector.Unboxed.foldM' 178 | , Data.Vector.Unboxed.ifoldM' 179 | , Data.Vector.Unboxed.foldM_ 180 | , Data.Vector.Unboxed.ifoldM_ 181 | , Data.Vector.Unboxed.foldM'_ 182 | , Data.Vector.Unboxed.ifoldM'_ 183 | 184 | -- * Prefix sums (scans) 185 | , Data.Vector.Unboxed.prescanl 186 | , Data.Vector.Unboxed.prescanl' 187 | , Data.Vector.Unboxed.postscanl 188 | , Data.Vector.Unboxed.postscanl' 189 | , Data.Vector.Unboxed.scanl 190 | , Data.Vector.Unboxed.scanl' 191 | , Data.Vector.Unboxed.prescanr 192 | , Data.Vector.Unboxed.prescanr' 193 | , Data.Vector.Unboxed.postscanr 194 | , Data.Vector.Unboxed.postscanr' 195 | , Data.Vector.Unboxed.scanr 196 | , Data.Vector.Unboxed.scanr' 197 | 198 | -- * Conversions 199 | -- ** Lists 200 | , Data.Vector.Unboxed.toList 201 | , Data.Vector.Unboxed.fromList 202 | , Data.Vector.Unboxed.fromListN 203 | 204 | -- ** Different vector types 205 | , Data.Vector.Unboxed.convert 206 | 207 | -- ** Mutable vectors 208 | , Data.Vector.Unboxed.freeze 209 | , Data.Vector.Unboxed.thaw 210 | , Data.Vector.Unboxed.copy 211 | ) where 212 | 213 | import qualified Data.Vector.Unboxed 214 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Unboxed/Partial.hs: -------------------------------------------------------------------------------- 1 | -- | Unboxed @Vector@ partial functions. Import as: 2 | -- 3 | -- > import qualified RIO.Vector.Unboxed.Partial as VU' 4 | module RIO.Vector.Unboxed.Partial 5 | ( 6 | -- * Accessors 7 | -- ** Indexing 8 | (Data.Vector.Unboxed.!) 9 | , Data.Vector.Unboxed.head 10 | , Data.Vector.Unboxed.last 11 | 12 | -- ** Monadic indexing 13 | , Data.Vector.Unboxed.indexM 14 | , Data.Vector.Unboxed.headM 15 | , Data.Vector.Unboxed.lastM 16 | 17 | -- ** Extracting subvectors 18 | , Data.Vector.Unboxed.init 19 | , Data.Vector.Unboxed.tail 20 | 21 | -- * Modifying vectors 22 | -- ** Bulk updates 23 | , (Data.Vector.Unboxed.//) 24 | , Data.Vector.Unboxed.update 25 | , Data.Vector.Unboxed.update_ 26 | 27 | -- ** Accumulations 28 | , Data.Vector.Unboxed.accum 29 | , Data.Vector.Unboxed.accumulate 30 | , Data.Vector.Unboxed.accumulate_ 31 | 32 | -- ** Permutations 33 | , Data.Vector.Unboxed.backpermute 34 | 35 | -- * Folding 36 | , Data.Vector.Unboxed.foldl1 37 | , Data.Vector.Unboxed.foldl1' 38 | , Data.Vector.Unboxed.foldr1 39 | , Data.Vector.Unboxed.foldr1' 40 | 41 | -- ** Specialised folds 42 | , Data.Vector.Unboxed.maximum 43 | , Data.Vector.Unboxed.maximumBy 44 | , Data.Vector.Unboxed.minimum 45 | , Data.Vector.Unboxed.minimumBy 46 | , Data.Vector.Unboxed.minIndex 47 | , Data.Vector.Unboxed.minIndexBy 48 | , Data.Vector.Unboxed.maxIndex 49 | , Data.Vector.Unboxed.maxIndexBy 50 | 51 | -- ** Monadic folds 52 | , Data.Vector.Unboxed.fold1M 53 | , Data.Vector.Unboxed.fold1M' 54 | , Data.Vector.Unboxed.fold1M_ 55 | , Data.Vector.Unboxed.fold1M'_ 56 | 57 | -- * Prefix sums (scans) 58 | , Data.Vector.Unboxed.scanl1 59 | , Data.Vector.Unboxed.scanl1' 60 | , Data.Vector.Unboxed.scanr1 61 | , Data.Vector.Unboxed.scanr1' 62 | ) where 63 | 64 | import qualified Data.Vector.Unboxed 65 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Unboxed/Unsafe.hs: -------------------------------------------------------------------------------- 1 | -- | Unoxed @Vector@ unsafe functions. These perform no bounds 2 | -- checking, and may cause segmentation faults etc.! Import as: 3 | -- 4 | -- > import qualified RIO.Vector.Unoxed.Unsafe as VU' 5 | module RIO.Vector.Unboxed.Unsafe 6 | ( 7 | -- * Accessors 8 | -- ** Indexing 9 | Data.Vector.Unboxed.unsafeIndex 10 | , Data.Vector.Unboxed.unsafeHead 11 | , Data.Vector.Unboxed.unsafeLast 12 | 13 | -- ** Monadic indexing 14 | , Data.Vector.Unboxed.unsafeIndexM 15 | , Data.Vector.Unboxed.unsafeHeadM 16 | , Data.Vector.Unboxed.unsafeLastM 17 | 18 | -- ** Extracting subvectors 19 | , Data.Vector.Unboxed.unsafeSlice 20 | , Data.Vector.Unboxed.unsafeInit 21 | , Data.Vector.Unboxed.unsafeTail 22 | , Data.Vector.Unboxed.unsafeTake 23 | , Data.Vector.Unboxed.unsafeDrop 24 | 25 | -- * Modifying vectors 26 | -- ** Bulk updates 27 | , Data.Vector.Unboxed.unsafeUpd 28 | , Data.Vector.Unboxed.unsafeUpdate 29 | , Data.Vector.Unboxed.unsafeUpdate_ 30 | 31 | -- ** Accumulations 32 | , Data.Vector.Unboxed.unsafeAccum 33 | , Data.Vector.Unboxed.unsafeAccumulate 34 | , Data.Vector.Unboxed.unsafeAccumulate_ 35 | 36 | -- ** Permutations 37 | , Data.Vector.Unboxed.unsafeBackpermute 38 | 39 | -- * Conversions 40 | -- ** Mutable vectors 41 | , Data.Vector.Unboxed.unsafeFreeze 42 | , Data.Vector.Unboxed.unsafeThaw 43 | , Data.Vector.Unboxed.unsafeCopy 44 | ) where 45 | 46 | import qualified Data.Vector.Unboxed 47 | -------------------------------------------------------------------------------- /rio/src/RIO/Vector/Unsafe.hs: -------------------------------------------------------------------------------- 1 | -- | Generic @Vector@ interface unsafe functions. These perform no bounds 2 | -- checking, and may cause segmentation faults etc.! Import as: 3 | -- 4 | -- > import qualified RIO.Vector.Unsafe as V' 5 | module RIO.Vector.Unsafe 6 | ( 7 | -- * Immutable vectors 8 | Data.Vector.Generic.Vector(..) 9 | 10 | -- * Accessors 11 | -- ** Indexing 12 | , Data.Vector.Generic.unsafeIndex 13 | , Data.Vector.Generic.unsafeHead 14 | , Data.Vector.Generic.unsafeLast 15 | 16 | -- ** Monadic indexing 17 | , Data.Vector.Generic.unsafeIndexM 18 | , Data.Vector.Generic.unsafeHeadM 19 | , Data.Vector.Generic.unsafeLastM 20 | 21 | -- ** Extracting subvectors 22 | , Data.Vector.Generic.unsafeSlice 23 | , Data.Vector.Generic.unsafeInit 24 | , Data.Vector.Generic.unsafeTail 25 | , Data.Vector.Generic.unsafeTake 26 | , Data.Vector.Generic.unsafeDrop 27 | 28 | -- * Modifying vectors 29 | -- ** Bulk updates 30 | , Data.Vector.Generic.unsafeUpd 31 | , Data.Vector.Generic.unsafeUpdate 32 | , Data.Vector.Generic.unsafeUpdate_ 33 | 34 | -- ** Accumulations 35 | , Data.Vector.Generic.unsafeAccum 36 | , Data.Vector.Generic.unsafeAccumulate 37 | , Data.Vector.Generic.unsafeAccumulate_ 38 | 39 | -- ** Permutations 40 | , Data.Vector.Generic.unsafeBackpermute 41 | 42 | -- * Conversions 43 | -- ** Mutable vectors 44 | , Data.Vector.Generic.unsafeFreeze 45 | , Data.Vector.Generic.unsafeThaw 46 | , Data.Vector.Generic.unsafeCopy 47 | ) where 48 | 49 | import qualified Data.Vector.Generic 50 | -------------------------------------------------------------------------------- /rio/src/RIO/Writer.hs: -------------------------------------------------------------------------------- 1 | -- | Provides reexports of 'MonadWriter' and related helpers. 2 | -- 3 | -- @since 0.1.4.0 4 | module RIO.Writer 5 | ( 6 | Control.Monad.Writer.MonadWriter (..) 7 | , Control.Monad.Writer.listens 8 | , Control.Monad.Writer.censor 9 | , Control.Monad.Writer.Writer 10 | , Control.Monad.Writer.runWriter 11 | , Control.Monad.Writer.execWriter 12 | , Control.Monad.Writer.mapWriter 13 | , Control.Monad.Writer.WriterT (..) 14 | , Control.Monad.Writer.execWriterT 15 | , Control.Monad.Writer.mapWriterT 16 | ) where 17 | 18 | import qualified Control.Monad.Writer 19 | -------------------------------------------------------------------------------- /rio/test/RIO/DequeSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleContexts #-} 2 | {-# LANGUAGE ScopedTypeVariables #-} 3 | module RIO.DequeSpec (spec) where 4 | 5 | import RIO 6 | import Test.Hspec 7 | import Test.Hspec.QuickCheck 8 | import Test.QuickCheck.Arbitrary 9 | import Test.QuickCheck.Gen 10 | import qualified Data.Vector as VB 11 | import qualified Data.Vector.Generic as VG 12 | import qualified Data.Vector.Unboxed as VU 13 | import qualified Data.Vector.Storable as VS 14 | import qualified Data.Vector.Generic.Mutable as V 15 | 16 | data DequeAction 17 | = PushFront Int 18 | | PushBack Int 19 | | PopFront 20 | | PopBack 21 | deriving Show 22 | instance Arbitrary DequeAction where 23 | arbitrary = oneof $ concat 24 | [ replicate 25 $ fmap PushFront arbitrary 25 | , replicate 25 $ fmap PushBack arbitrary 26 | , [return PopFront, return PopBack] 27 | ] 28 | 29 | manyPushes :: [DequeAction] 30 | manyPushes = concat 31 | [ replicate 50 $ PushBack 0 32 | , replicate 50 PopFront 33 | , replicate 50 $ PushFront 0 34 | , replicate 50 PopBack 35 | ] 36 | 37 | specialCase :: [DequeAction] 38 | specialCase = 39 | [PushBack 9, PushBack 5,PushBack 11,PushBack 2,PushBack 13,PushBack 10,PushBack 4,PushBack 13,PushBack 7,PushBack 8,PushBack 6,PushBack 4,PushBack 7,PushBack 9,PushBack 10,PushBack 3,PushBack 2,PushBack 12,PushBack 12 ,PushBack 6,PushBack 3,PushBack 5,PushBack 14,PushBack 14,PushBack 11,PushBack 8,PopFront,PopFront,PopFront,PushBack 11,PushBack 3,PopFront,PopFront,PushBack 13,PushBack 12,PopFront,PushBack 10,PushBack 7,PopFront,PopFront,PushBack 13,PushBack 9,PopFront,PushBack 7,PushBack 2,PopFront,PopFront,PushBack 6,PushBack 4,PopFront,PopFront,PopFront,PushBack 9,PushBack 3,PopFront,PushBack 10,PushBack 6,PopFront,PopFront,PopFront,PushBack 12,PushBack 5,PopFront,PushBack 12,PushBack 5,PopFront,PushBack 6,PushBack 4,PopFront,PopFront,PopFront,PushBack 14,PushBack 10,PopFront,PushBack 14,PushBack 10,PopFront,PushBack 11,PushBack 8,PopFront,PushBack 8,PushBack 2,PopFront,PopFront,PopFront,PushBack 13,PushBack 7,PopFront,PushBack 12,PushBack 5,PopFront,PushBack 10,PushBack 8, PopFront,PushBack 7,PushBack 2,PopFront,PopFront,PushBack 9,PushBack 4,PopFront,PopFront,PopFront,PopFront,PopFront,PopFront,PopFront,PopFront,PushBack 4,PushBack 9,PushBack 3,PushBack 10,PushBack 6,PushBack 4,PushBack 13,PushBack 7,PushBack 9,PushBack 3,PopFront] 40 | 41 | spec :: Spec 42 | spec = do 43 | let runActions 44 | :: forall v . (VG.Vector v Int, Show (v Int), Eq (v Int)) 45 | => Proxy v 46 | -> [DequeAction] 47 | -> IO () 48 | runActions proxy actions = do 49 | base <- newIORef [] :: IO (IORef [Int]) 50 | tested <- newDeque :: IO (Deque (VG.Mutable v) (PrimState IO) Int) 51 | for_ (PopFront : PopBack : actions) $ \action -> do 52 | case action of 53 | PushFront i -> do 54 | pushFrontRef base i 55 | pushFrontDeque tested i 56 | same proxy base tested 57 | PushBack i -> do 58 | pushBackRef base i 59 | pushBackDeque tested i 60 | same proxy base tested 61 | PopFront -> do 62 | expected <- popFrontRef base 63 | actual <- popFrontDeque tested 64 | actual `shouldBe` expected 65 | same proxy base tested 66 | PopBack -> do 67 | expected <- popBackRef base 68 | actual <- popBackDeque tested 69 | actual `shouldBe` expected 70 | same proxy base tested 71 | let drain = do 72 | expected <- popBackRef base 73 | actual <- popBackDeque tested 74 | actual `shouldBe` expected 75 | case actual of 76 | Just _ -> drain 77 | Nothing -> return $! () 78 | drain 79 | test name proxy = describe name $ do 80 | prop "arbitrary actions" $ runActions proxy 81 | it "many pushes" $ runActions proxy manyPushes 82 | it "special case" $ runActions proxy specialCase 83 | 84 | test "UDeque" (Proxy :: Proxy VU.Vector) 85 | test "SDeque" (Proxy :: Proxy VS.Vector) 86 | test "BDeque" (Proxy :: Proxy VB.Vector) 87 | 88 | pushFrontRef :: IORef [Int] -> Int -> IO () 89 | pushFrontRef ref i = modifyIORef ref (i:) 90 | 91 | pushBackRef :: IORef [Int] -> Int -> IO () 92 | pushBackRef ref i = modifyIORef ref (++ [i]) 93 | 94 | popFrontRef :: IORef [Int] -> IO (Maybe Int) 95 | popFrontRef ref = do 96 | is <- readIORef ref 97 | case is of 98 | i:is' -> do 99 | writeIORef ref is' 100 | pure $ Just i 101 | [] -> pure Nothing 102 | 103 | popBackRef :: IORef [Int] -> IO (Maybe Int) 104 | popBackRef ref = do 105 | is <- readIORef ref 106 | case reverse is of 107 | i:is' -> do 108 | writeIORef ref $ reverse is' 109 | pure $ Just i 110 | [] -> pure Nothing 111 | 112 | same :: 113 | forall v. (Show (v Int), Eq (v Int), VG.Vector v Int) 114 | => Proxy v 115 | -> IORef [Int] 116 | -> Deque (VG.Mutable v) (PrimState IO) Int 117 | -> IO () 118 | same proxy ref deque = do 119 | fromRef <- readIORef ref 120 | fromRight <- foldrDeque (\i rest -> pure $ i : rest) [] deque 121 | fromRight `shouldBe` fromRef 122 | fromLeft <- foldlDeque (\rest i -> pure $ i : rest) [] deque 123 | fromLeft `shouldBe` reverse fromRef 124 | dequeToList deque `shouldReturn` fromRef 125 | dequeToVector deque `shouldReturn` (VU.fromList fromRef :: VU.Vector Int) 126 | uv :: v Int <- freezeDeque deque 127 | uv `shouldBe` VG.fromList fromRef 128 | -------------------------------------------------------------------------------- /rio/test/RIO/FileSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NamedFieldPuns #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | {-# LANGUAGE NoImplicitPrelude #-} 4 | module RIO.FileSpec where 5 | 6 | import Test.Hspec 7 | import System.FilePath (()) 8 | import UnliftIO.Temporary (withSystemTempDirectory) 9 | 10 | import RIO 11 | import qualified RIO.ByteString as BS 12 | import qualified RIO.File as SUT 13 | 14 | spec :: Spec 15 | spec = do 16 | describe "ensureFileDurable" $ do 17 | it "ensures a file is durable with an fsync" $ 18 | withSystemTempDirectory "rio" $ \dir -> do 19 | let fp = dir "ensure_file_durable" 20 | writeFileUtf8 fp "Hello World" 21 | SUT.ensureFileDurable fp 22 | contents <- BS.readFile fp 23 | contents `shouldBe` "Hello World" 24 | 25 | describe "withBinaryFileDurableAtomic" $ do 26 | context "read/write" $ do 27 | it "works correctly" $ do 28 | withSystemTempDirectory "rio" $ \dir -> do 29 | let fp = dir "ensure_file_durable_atomic" 30 | writeFileUtf8 fp "Hello World" 31 | SUT.withBinaryFileDurableAtomic fp ReadWriteMode $ \h -> do 32 | input <- BS.hGetLine h 33 | input `shouldBe` "Hello World" 34 | BS.hPut h "Goodbye World" 35 | 36 | context "happy path" $ do 37 | it "works the same as withFile" $ do 38 | withSystemTempDirectory "rio" $ \dir -> do 39 | let fp = dir "with_file_durable_atomic" 40 | SUT.withBinaryFileDurableAtomic fp WriteMode $ \h -> 41 | BS.hPut h "Hello World" 42 | contents <- BS.readFile fp 43 | contents `shouldBe` "Hello World" 44 | 45 | describe "withBinaryFileDurable" $ do 46 | context "happy path" $ do 47 | it "works the same as withFile" $ do 48 | withSystemTempDirectory "rio" $ \dir -> do 49 | let fp = dir "with_file_durable" 50 | SUT.withBinaryFileDurable fp WriteMode $ \h -> 51 | BS.hPut h "Hello World" 52 | contents <- BS.readFile fp 53 | contents `shouldBe` "Hello World" 54 | -------------------------------------------------------------------------------- /rio/test/RIO/ListSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | module RIO.ListSpec where 3 | 4 | import Test.Hspec 5 | import RIO 6 | import qualified RIO.List as List 7 | 8 | data TestType = TestType { testTypeContents :: Int } 9 | deriving (Eq, Show) 10 | 11 | testTypeList :: [TestType] 12 | testTypeList = [TestType { testTypeContents = 1 }, TestType { testTypeContents = 0 }] 13 | 14 | spec :: Spec 15 | spec = do 16 | describe "dropPrefix" $ do 17 | it "present" $ List.dropPrefix "foo" "foobar" `shouldBe` "bar" 18 | it "absent" $ List.dropPrefix "bar" "foobar" `shouldBe` "foobar" 19 | describe "dropSuffix" $ do 20 | it "present" $ List.dropSuffix "bar" "foobar" `shouldBe` "foo" 21 | it "absent" $ List.dropSuffix "foo" "foobar" `shouldBe` "foobar" 22 | describe "maximumByMaybe" $ do 23 | it "should support elements that do not have an Ord instance" $ 24 | List.maximumByMaybe (compare `on` testTypeContents) testTypeList `shouldBe` (Just TestType { testTypeContents = 1}) 25 | describe "minimumByMaybe" $ do 26 | it "should support elements that do not have an Ord instance" $ 27 | List.minimumByMaybe (compare `on` testTypeContents) testTypeList `shouldBe` (Just TestType { testTypeContents = 0}) 28 | -------------------------------------------------------------------------------- /rio/test/RIO/LoggerSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | module RIO.LoggerSpec (spec) where 4 | 5 | import Test.Hspec 6 | import RIO 7 | import Data.ByteString.Builder (toLazyByteString) 8 | 9 | spec :: Spec 10 | spec = do 11 | it "sanity" $ do 12 | (ref, options) <- logOptionsMemory 13 | withLogFunc options $ \lf -> runRIO lf $ do 14 | logDebug "should not appear" 15 | logInfo "should appear" 16 | builder <- readIORef ref 17 | toLazyByteString builder `shouldBe` "should appear\n" 18 | it "sticky" $ do 19 | (ref, options) <- logOptionsMemory 20 | withLogFunc options $ \lf -> runRIO lf $ do 21 | logSticky "ABC" 22 | logDebug "should not appear" 23 | logInfo "should appear" 24 | logStickyDone "XYZ" 25 | builder <- readIORef ref 26 | toLazyByteString builder `shouldBe` "ABC\b\b\b \b\b\bshould appear\nABC\b\b\b \b\b\bXYZ\n" 27 | it "stickyUnicode" $ do 28 | (ref, options) <- logOptionsMemory 29 | withLogFunc options $ \lf -> runRIO lf $ do 30 | logSticky "ö" 31 | logStickyDone "." 32 | builder <- readIORef ref 33 | toLazyByteString builder `shouldBe` "\195\182\b \b.\n" 34 | it "stickyAnsiEscape" $ do 35 | (ref, options) <- logOptionsMemory 36 | withLogFunc options $ \lf -> runRIO lf $ do 37 | logSticky "\ESC[31mABC\ESC[0m" 38 | logStickyDone "." 39 | builder <- readIORef ref 40 | toLazyByteString builder `shouldBe` "\ESC[31mABC\ESC[0m\b\b\b \b\b\b.\n" 41 | it "setLogMinLevelIO" $ do 42 | (ref, options) <- logOptionsMemory 43 | logLevelRef <- newIORef LevelDebug 44 | withLogFunc (options & setLogMinLevelIO (readIORef logLevelRef)) 45 | $ \lf -> runRIO lf $ do 46 | logDebug "should appear" 47 | -- reset log min level to info 48 | atomicModifyIORef' logLevelRef (\_ -> (LevelInfo, ())) 49 | logDebug "should not appear" 50 | builder <- readIORef ref 51 | toLazyByteString builder `shouldBe` "should appear\n" 52 | it "setLogVerboseFormatIO" $ do 53 | (ref, options) <- logOptionsMemory 54 | logVerboseFormatRef <- newIORef True 55 | withLogFunc (options & setLogVerboseFormatIO (readIORef logVerboseFormatRef)) 56 | $ \lf -> runRIO lf $ do 57 | logInfo "verbose log" 58 | -- reset verbose format 59 | atomicModifyIORef' logVerboseFormatRef (\_ -> (False, ())) 60 | logInfo "no verbose log" 61 | builder <- readIORef ref 62 | toLazyByteString builder `shouldBe` "[info] verbose log\nno verbose log\n" 63 | it "noLogging" $ do 64 | (ref, options) <- logOptionsMemory 65 | withLogFunc (options & setLogVerboseFormat True) $ \lf -> runRIO lf $ do 66 | logInfo "should appear" 67 | noLogging $ logInfo "should not appear" 68 | builder <- readIORef ref 69 | toLazyByteString builder `shouldBe` "[info] should appear\n" 70 | it "setLogFormat" $ do 71 | (ref, options) <- logOptionsMemory 72 | let format = ("[context] " <>) 73 | withLogFunc (options & setLogFormat format) $ \lf -> runRIO lf $ do 74 | logInfo "should be formatted" 75 | builder <- readIORef ref 76 | toLazyByteString builder `shouldBe` "[context] should be formatted\n" 77 | it "noSource" $ do 78 | (ref, options) <- logOptionsMemory 79 | withLogFunc options $ \lf -> runRIO lf $ do 80 | logInfoS "tests" "should appear" 81 | builder <- readIORef ref 82 | toLazyByteString builder `shouldBe` "(tests) should appear\n" 83 | it "noSource verbose" $ do 84 | (ref, options) <- logOptionsMemory 85 | withLogFunc (options & setLogVerboseFormat True) $ \lf -> runRIO lf $ do 86 | logInfoS "tests" "should appear" 87 | builder <- readIORef ref 88 | toLazyByteString builder `shouldBe` "[info] (tests) should appear\n" 89 | -------------------------------------------------------------------------------- /rio/test/RIO/Prelude/ExtraSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | 4 | module RIO.Prelude.ExtraSpec (spec) where 5 | 6 | import RIO 7 | import RIO.Process 8 | import Test.Hspec 9 | 10 | import qualified Data.Map as Map 11 | import qualified Data.Text as T 12 | import qualified System.FilePath as FP 13 | 14 | spec :: Spec 15 | spec = do 16 | describe "foldMapM" $ do 17 | it "sanity" $ do 18 | let helper :: Applicative f => Int -> f [Int] 19 | helper = pure . pure 20 | res <- foldMapM helper [1..10] 21 | res `shouldBe` [1..10] 22 | describe "augmentPathMap" $ do 23 | -- https://github.com/commercialhaskell/rio/issues/234 24 | it "Doesn't duplicate PATH keys on windows" $ do 25 | let pathKey :: T.Text 26 | #if WINDOWS 27 | pathKey = "Path" 28 | #else 29 | pathKey = "PATH" 30 | #endif 31 | origEnv :: EnvVars 32 | origEnv = Map.fromList [ ("foo", "3") 33 | , ("bar", "baz") 34 | , (pathKey, makePath ["/local/bin", "/usr/bin"]) 35 | ] 36 | let res = second (fmap getPaths . Map.lookup "PATH") $ augmentPathMap ["/bin"] origEnv 37 | res `shouldBe` Right (Just ["/bin", "/local/bin", "/usr/bin"]) 38 | where 39 | makePath :: [T.Text] -> T.Text 40 | makePath = T.intercalate (T.singleton FP.searchPathSeparator) 41 | 42 | getPaths :: T.Text -> [T.Text] 43 | getPaths = fmap T.pack . FP.splitSearchPath . T.unpack 44 | -------------------------------------------------------------------------------- /rio/test/RIO/Prelude/IOSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | {-# LANGUAGE NoImplicitPrelude #-} 3 | {-# LANGUAGE ViewPatterns #-} 4 | module RIO.Prelude.IOSpec (spec) where 5 | 6 | import RIO 7 | import Test.Hspec 8 | import Test.Hspec.QuickCheck 9 | import qualified RIO.ByteString as B 10 | import qualified RIO.Text as T 11 | 12 | spec :: Spec 13 | spec = do 14 | prop "binary file read/write" $ \(B.pack -> bs1) -> 15 | withSystemTempFile "binary-read-write" $ \fp h -> do 16 | hClose h 17 | writeFileBinary fp bs1 18 | bs2 <- readFileBinary fp 19 | bs2 `shouldBe` bs1 20 | -- filter our \r for Windows 21 | prop "text file read/write" $ \(T.pack . filter (/= '\r') -> text1) -> 22 | withSystemTempFile "binary-read-write" $ \fp h -> do 23 | hClose h 24 | writeFileUtf8 fp text1 25 | text2 <- readFileUtf8 fp 26 | text2 `shouldBe` text1 27 | -------------------------------------------------------------------------------- /rio/test/RIO/Prelude/RIOSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | {-# LANGUAGE NoImplicitPrelude #-} 3 | {-# LANGUAGE ViewPatterns #-} 4 | module RIO.Prelude.RIOSpec (spec) where 5 | 6 | import RIO 7 | import RIO.State 8 | import RIO.Writer 9 | import Test.Hspec 10 | 11 | spec :: Spec 12 | spec = do 13 | describe "RIO writer instance" $ do 14 | it "tell works" $ do 15 | ref <- newSomeRef (mempty :: Text) 16 | runRIO ref $ do 17 | tell "hello\n" 18 | tell "world\n" 19 | contents <- readSomeRef ref 20 | contents `shouldBe` "hello\nworld\n" 21 | 22 | it "listen works" $ do 23 | ref <- newSomeRef (mempty :: Text) 24 | ((), str) <- runRIO ref $ listen $ do 25 | tell "hello\n" 26 | tell "world\n" 27 | contents <- readSomeRef ref 28 | contents `shouldBe` "" 29 | str `shouldBe` "hello\nworld\n" 30 | 31 | it "pass works" $ do 32 | ref <- newSomeRef (mempty :: Text) 33 | () <- runRIO ref $ pass $ do 34 | tell "hello\n" 35 | tell "world\n" 36 | return ((), \a -> a <> "!") 37 | contents <- readSomeRef ref 38 | contents `shouldBe` "hello\nworld\n!" 39 | 40 | describe "RIO state instance" $ do 41 | it "get works" $ do 42 | ref <- newSomeRef (mempty :: Text) 43 | result <- runRIO ref $ do 44 | put "hello world" 45 | x <- get 46 | return x 47 | result `shouldBe` "hello world" 48 | 49 | it "state works" $ do 50 | ref <- newSomeRef (mempty :: Text) 51 | _newRef <- newSomeRef ("Hello World!" :: Text) 52 | () <- runRIO ref $ state (\_ -> ((), "Hello World!")) 53 | contents <- readSomeRef ref 54 | contents `shouldBe` "Hello World!" 55 | -------------------------------------------------------------------------------- /rio/test/RIO/Prelude/SimpleSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | {-# LANGUAGE NoImplicitPrelude #-} 3 | {-# LANGUAGE ViewPatterns #-} 4 | module RIO.Prelude.SimpleSpec (spec) where 5 | 6 | import RIO 7 | import RIO.Process 8 | import Test.Hspec 9 | 10 | spec :: Spec 11 | spec = do 12 | it "logging works" $ asIO $ runSimpleApp $ logDebug "logging allowed" 13 | it "process calling works" $ asIO $ runSimpleApp $ proc "echo" ["hello"] runProcess_ 14 | -------------------------------------------------------------------------------- /rio/test/RIO/PreludeSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | module RIO.PreludeSpec (spec) where 4 | 5 | import Test.Hspec 6 | import RIO 7 | 8 | spec :: Spec 9 | spec = do 10 | describe "URef" $ do 11 | it "sanity" $ do 12 | ref <- newURef (0 :: Int) 13 | x <- readURef ref 14 | x `shouldBe` 0 15 | writeURef ref 1 16 | y <- readURef ref 17 | y `shouldBe` 1 18 | modifyURef ref (+ 1) 19 | z <- readURef ref 20 | z `shouldBe` 2 21 | describe "whenM" $ do 22 | it "returns True" $ do 23 | ref <- newIORef False 24 | whenM (return True) (writeIORef ref True) 25 | readIORef ref `shouldReturn` True 26 | it "returns False" $ do 27 | ref <- newIORef False 28 | whenM (return False) (writeIORef ref True) 29 | readIORef ref `shouldReturn` False 30 | describe "unlessM" $ do 31 | it "returns True" $ do 32 | ref <- newIORef False 33 | unlessM (return True) (writeIORef ref True) 34 | readIORef ref `shouldReturn` False 35 | it "returns False" $ do 36 | ref <- newIORef False 37 | unlessM (return False) (writeIORef ref True) 38 | readIORef ref `shouldReturn` True 39 | -------------------------------------------------------------------------------- /rio/test/RIO/TextSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | module RIO.TextSpec where 4 | 5 | import Test.Hspec 6 | import RIO 7 | import qualified RIO.Text as T 8 | 9 | spec :: Spec 10 | spec = do 11 | describe "dropPrefix" $ do 12 | it "present" $ T.dropPrefix "foo" "foobar" `shouldBe` "bar" 13 | it "absent" $ T.dropPrefix "bar" "foobar" `shouldBe` "foobar" 14 | describe "dropSuffix" $ do 15 | it "present" $ T.dropSuffix "bar" "foobar" `shouldBe` "foo" 16 | it "absent" $ T.dropSuffix "foo" "foobar" `shouldBe` "foobar" 17 | -------------------------------------------------------------------------------- /rio/test/Spec.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -F -pgmF hspec-discover #-} 2 | -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | resolver: lts-18.5 2 | packages: 3 | - rio 4 | - rio-orphans 5 | extra-deps: 6 | - typed-process-0.2.6.0@sha256:c901c13d491441830eb23132ad6968243a56b98161629d260a26c0b13c735fcd,2136 7 | - unliftio-0.2.14@sha256:7e6d3de70ad13e2efd14d417a19c1c5b33250cf0f6be9dfc907b39535a661c4a,3366 8 | 9 | nix: 10 | packages: [zlib] 11 | -------------------------------------------------------------------------------- /stack.yaml.lock: -------------------------------------------------------------------------------- 1 | # This file was autogenerated by Stack. 2 | # You should not edit this file by hand. 3 | # For more information, please see the documentation at: 4 | # https://docs.haskellstack.org/en/stable/lock_files 5 | 6 | packages: 7 | - completed: 8 | hackage: typed-process-0.2.6.0@sha256:c901c13d491441830eb23132ad6968243a56b98161629d260a26c0b13c735fcd,2136 9 | pantry-tree: 10 | size: 529 11 | sha256: 2ef79f15f1f391e49dc522076f6d1584c7b305bf2aaa0dfec4dc0d4b61f31111 12 | original: 13 | hackage: typed-process-0.2.6.0@sha256:c901c13d491441830eb23132ad6968243a56b98161629d260a26c0b13c735fcd,2136 14 | - completed: 15 | hackage: unliftio-0.2.14@sha256:7e6d3de70ad13e2efd14d417a19c1c5b33250cf0f6be9dfc907b39535a661c4a,3366 16 | pantry-tree: 17 | size: 2352 18 | sha256: 7f07d0b0ed71be25a9ea235b2974e1d2ff282210f968fbf25b932cb69351b293 19 | original: 20 | hackage: unliftio-0.2.14@sha256:7e6d3de70ad13e2efd14d417a19c1c5b33250cf0f6be9dfc907b39535a661c4a,3366 21 | snapshots: 22 | - completed: 23 | size: 585817 24 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/5.yaml 25 | sha256: 22d24d0dacad9c1450b9a174c28d203f9bb482a2a8da9710a2f2a9f4afee2887 26 | original: lts-18.5 27 | --------------------------------------------------------------------------------