packages feed

hw-prelude (empty) → 0.0.0.1

raw patch · 15 files changed

+855/−0 lines, 15 filesdep +Win32dep +asyncdep +base

Dependencies added: Win32, async, base, bytestring, contravariant, directory, filepath, network, process, resourcet, text, unliftio

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for hw-prelude++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,202 @@++                                 Apache License+                           Version 2.0, January 2004+                        http://www.apache.org/licenses/++   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION++   1. Definitions.++      "License" shall mean the terms and conditions for use, reproduction,+      and distribution as defined by Sections 1 through 9 of this document.++      "Licensor" shall mean the copyright owner or entity authorized by+      the copyright owner that is granting the License.++      "Legal Entity" shall mean the union of the acting entity and all+      other entities that control, are controlled by, or are under common+      control with that entity. For the purposes of this definition,+      "control" means (i) the power, direct or indirect, to cause the+      direction or management of such entity, whether by contract or+      otherwise, or (ii) ownership of fifty percent (50%) or more of the+      outstanding shares, or (iii) beneficial ownership of such entity.++      "You" (or "Your") shall mean an individual or Legal Entity+      exercising permissions granted by this License.++      "Source" form shall mean the preferred form for making modifications,+      including but not limited to software source code, documentation+      source, and configuration files.++      "Object" form shall mean any form resulting from mechanical+      transformation or translation of a Source form, including but+      not limited to compiled object code, generated documentation,+      and conversions to other media types.++      "Work" shall mean the work of authorship, whether in Source or+      Object form, made available under the License, as indicated by a+      copyright notice that is included in or attached to the work+      (an example is provided in the Appendix below).++      "Derivative Works" shall mean any work, whether in Source or Object+      form, that is based on (or derived from) the Work and for which the+      editorial revisions, annotations, elaborations, or other modifications+      represent, as a whole, an original work of authorship. For the purposes+      of this License, Derivative Works shall not include works that remain+      separable from, or merely link (or bind by name) to the interfaces of,+      the Work and Derivative Works thereof.++      "Contribution" shall mean any work of authorship, including+      the original version of the Work and any modifications or additions+      to that Work or Derivative Works thereof, that is intentionally+      submitted to Licensor for inclusion in the Work by the copyright owner+      or by an individual or Legal Entity authorized to submit on behalf of+      the copyright owner. For the purposes of this definition, "submitted"+      means any form of electronic, verbal, or written communication sent+      to the Licensor or its representatives, including but not limited to+      communication on electronic mailing lists, source code control systems,+      and issue tracking systems that are managed by, or on behalf of, the+      Licensor for the purpose of discussing and improving the Work, but+      excluding communication that is conspicuously marked or otherwise+      designated in writing by the copyright owner as "Not a Contribution."++      "Contributor" shall mean Licensor and any individual or Legal Entity+      on behalf of whom a Contribution has been received by Licensor and+      subsequently incorporated within the Work.++   2. Grant of Copyright License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      copyright license to reproduce, prepare Derivative Works of,+      publicly display, publicly perform, sublicense, and distribute the+      Work and such Derivative Works in Source or Object form.++   3. Grant of Patent License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      (except as stated in this section) patent license to make, have made,+      use, offer to sell, sell, import, and otherwise transfer the Work,+      where such license applies only to those patent claims licensable+      by such Contributor that are necessarily infringed by their+      Contribution(s) alone or by combination of their Contribution(s)+      with the Work to which such Contribution(s) was submitted. If You+      institute patent litigation against any entity (including a+      cross-claim or counterclaim in a lawsuit) alleging that the Work+      or a Contribution incorporated within the Work constitutes direct+      or contributory patent infringement, then any patent licenses+      granted to You under this License for that Work shall terminate+      as of the date such litigation is filed.++   4. Redistribution. You may reproduce and distribute copies of the+      Work or Derivative Works thereof in any medium, with or without+      modifications, and in Source or Object form, provided that You+      meet the following conditions:++      (a) You must give any other recipients of the Work or+          Derivative Works a copy of this License; and++      (b) You must cause any modified files to carry prominent notices+          stating that You changed the files; and++      (c) You must retain, in the Source form of any Derivative Works+          that You distribute, all copyright, patent, trademark, and+          attribution notices from the Source form of the Work,+          excluding those notices that do not pertain to any part of+          the Derivative Works; and++      (d) If the Work includes a "NOTICE" text file as part of its+          distribution, then any Derivative Works that You distribute must+          include a readable copy of the attribution notices contained+          within such NOTICE file, excluding those notices that do not+          pertain to any part of the Derivative Works, in at least one+          of the following places: within a NOTICE text file distributed+          as part of the Derivative Works; within the Source form or+          documentation, if provided along with the Derivative Works; or,+          within a display generated by the Derivative Works, if and+          wherever such third-party notices normally appear. The contents+          of the NOTICE file are for informational purposes only and+          do not modify the License. You may add Your own attribution+          notices within Derivative Works that You distribute, alongside+          or as an addendum to the NOTICE text from the Work, provided+          that such additional attribution notices cannot be construed+          as modifying the License.++      You may add Your own copyright statement to Your modifications and+      may provide additional or different license terms and conditions+      for use, reproduction, or distribution of Your modifications, or+      for any such Derivative Works as a whole, provided Your use,+      reproduction, and distribution of the Work otherwise complies with+      the conditions stated in this License.++   5. Submission of Contributions. Unless You explicitly state otherwise,+      any Contribution intentionally submitted for inclusion in the Work+      by You to the Licensor shall be under the terms and conditions of+      this License, without any additional terms or conditions.+      Notwithstanding the above, nothing herein shall supersede or modify+      the terms of any separate license agreement you may have executed+      with Licensor regarding such Contributions.++   6. Trademarks. This License does not grant permission to use the trade+      names, trademarks, service marks, or product names of the Licensor,+      except as required for reasonable and customary use in describing the+      origin of the Work and reproducing the content of the NOTICE file.++   7. Disclaimer of Warranty. Unless required by applicable law or+      agreed to in writing, Licensor provides the Work (and each+      Contributor provides its Contributions) on an "AS IS" BASIS,+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or+      implied, including, without limitation, any warranties or conditions+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A+      PARTICULAR PURPOSE. You are solely responsible for determining the+      appropriateness of using or redistributing the Work and assume any+      risks associated with Your exercise of permissions under this License.++   8. Limitation of Liability. In no event and under no legal theory,+      whether in tort (including negligence), contract, or otherwise,+      unless required by applicable law (such as deliberate and grossly+      negligent acts) or agreed to in writing, shall any Contributor be+      liable to You for damages, including any direct, indirect, special,+      incidental, or consequential damages of any character arising as a+      result of this License or out of the use or inability to use the+      Work (including but not limited to damages for loss of goodwill,+      work stoppage, computer failure or malfunction, or any and all+      other commercial damages or losses), even if such Contributor+      has been advised of the possibility of such damages.++   9. Accepting Warranty or Additional Liability. While redistributing+      the Work or Derivative Works thereof, You may choose to offer,+      and charge a fee for, acceptance of support, warranty, indemnity,+      or other liability obligations and/or rights consistent with this+      License. However, in accepting such obligations, You may act only+      on Your own behalf and on Your sole responsibility, not on behalf+      of any other Contributor, and only if You agree to indemnify,+      defend, and hold each Contributor harmless for any liability+      incurred by, or claims asserted against, such Contributor by reason+      of your accepting any such warranty or additional liability.++   END OF TERMS AND CONDITIONS++   APPENDIX: How to apply the Apache License to your work.++      To apply the Apache License to your work, attach the following+      boilerplate notice, with the fields enclosed by brackets "[]"+      replaced with your own identifying information. (Don't include+      the brackets!)  The text should be enclosed in the appropriate+      comment syntax for the file format. We also recommend that a+      file or class name and description of purpose be included on the+      same "printed page" as the copyright notice for easier+      identification within third-party archives.++   Copyright [yyyy] [name of copyright owner]++   Licensed under the Apache License, Version 2.0 (the "License");+   you may not use this file except in compliance with the License.+   You may obtain a copy of the License at++       http://www.apache.org/licenses/LICENSE-2.0++   Unless required by applicable law or agreed to in writing, software+   distributed under the License is distributed on an "AS IS" BASIS,+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+   See the License for the specific language governing permissions and+   limitations under the License.
+ README.md view
@@ -0,0 +1,1 @@+# Opinionated prelude library
+ hw-prelude.cabal view
@@ -0,0 +1,91 @@+cabal-version:          3.4+name:                   hw-prelude+version:                0.0.0.1+synopsis:               Opinionated prelude library+description:            Opinionated prelude library.+license:                Apache-2.0+license-file:           LICENSE+author:                 John Ky+maintainer:             newhoggy@gmail.com+copyright:              2024 John Ky+category:               Development+build-type:             Simple+extra-doc-files:        CHANGELOG.md+extra-source-files:     README.md++source-repository head+  type:                 git+  location:             https://github.com/haskell-works/hw-prelude++common base                       { build-depends: base                       >= 4.13       && < 5      }++common async                      { build-depends: async                                       < 2.3    }+common bytestring                 { build-depends: bytestring                                  < 0.13   }+common contravariant              { build-depends: contravariant                               < 1.6    }+common directory                  { build-depends: directory                                   < 1.4    }+common filepath                   { build-depends: filepath                                    < 1.6    }+common network                    { build-depends: network                                     < 3.3    }+common process                    { build-depends: process                                     < 1.7    }+common resourcet                  { build-depends: resourcet                                   < 1.4    }+common text                       { build-depends: text                                        < 3      }+common unliftio                   { build-depends: unliftio                                    < 0.3    }++common hw-prelude                 { build-depends: hw-prelude                                           }++common Win32+  if os(windows)+    build-depends:      Win32   >= 2.5.4.1 && < 3++flag werror+  description: Enable -Werror+  manual: True+  default: False++common project-config+  default-language:     Haskell2010+  default-extensions:   BlockArguments+                        DataKinds+                        DeriveGeneric+                        DuplicateRecordFields+                        FlexibleContexts+                        FlexibleInstances+                        LambdaCase+                        NoImplicitPrelude+                        OverloadedStrings+                        RankNTypes+                        ScopedTypeVariables+                        TypeApplications+                        TypeOperators+  ghc-options:          -Wall++  if flag(werror)+    ghc-options:        -Werror++library+  import:               base, project-config,+                        async,+                        bytestring,+                        contravariant,+                        directory,+                        filepath,+                        network,+                        process,+                        resourcet,+                        text,+                        unliftio,+                        Win32,++  if os(windows)+    exposed-modules:    HaskellWorks.IO.Win32.NamedPipe++  exposed-modules:      HaskellWorks.Control.Monad+                        HaskellWorks.Data.String+                        HaskellWorks.Error+                        HaskellWorks.Error.Types+                        HaskellWorks.IO.Network.NamedPipe+                        HaskellWorks.IO.Network.Port+                        HaskellWorks.IO.Network.Socket+                        HaskellWorks.IO.Process+                        HaskellWorks.Prelude+                        HaskellWorks.Unsafe+  hs-source-dirs:       src
+ src/HaskellWorks/Control/Monad.hs view
@@ -0,0 +1,32 @@+module HaskellWorks.Control.Monad+  ( repeatNUntilM_,+    repeatNWhileM_,+  ) where++import           HaskellWorks.Prelude++-- | Repeat an action n times until the action returns True.+repeatNUntilM_ :: ()+  => Monad m+  => Int+  -> (Int -> m Bool)+  -> m ()+repeatNUntilM_ n action = go 0+  where+    go i =+      when (i < n) $ do+        shouldTerminate <- action i+        unless shouldTerminate $ go (i + 1)++-- | Repeat an action n times while the action returns True.+repeatNWhileM_ :: ()+  => Monad m+  => Int+  -> (Int -> m Bool)+  -> m ()+repeatNWhileM_ n action = go 0+  where+    go i =+      when (i < n) $ do+        shouldContinue <- action i+        when shouldContinue $ go (i + 1)
+ src/HaskellWorks/Data/String.hs view
@@ -0,0 +1,8 @@+module HaskellWorks.Data.String+  ( unlines+  , unwords+  , words+  , lines+  ) where++import           Data.String
+ src/HaskellWorks/Error.hs view
@@ -0,0 +1,28 @@+module HaskellWorks.Error+  ( onLeft,+    onNothing,+    onLeftM,+    onNothingM,+  ) where++import           HaskellWorks.Prelude++onLeft :: forall e a m. ()+  => Monad m+  => (e -> m a) -> Either e a -> m a+onLeft f = either f pure++onNothing :: forall a m. ()+  => Monad m+  => m a -> Maybe a -> m a+onNothing h = maybe h return++onLeftM :: forall e a m. ()+  => Monad m+  => (e -> m a) -> m (Either e a) -> m a+onLeftM f action = onLeft f =<< action++onNothingM :: forall a m. ()+  => Monad m+  => m a -> m (Maybe a) -> m a+onNothingM h f = onNothing h =<< f
+ src/HaskellWorks/Error/Types.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE DeriveGeneric #-}++module HaskellWorks.Error.Types+  ( GenericError(..),+    TimedOut(..),+  ) where++import           HaskellWorks.Prelude++newtype GenericError = GenericError+  { message :: Text+  }+  deriving (Generic, Eq, Show)++newtype TimedOut = TimedOut+  { message :: Text+  }+  deriving (Generic, Eq, Show)
+ src/HaskellWorks/IO/Network/NamedPipe.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE CPP #-}++{-# OPTIONS_GHC -Wno-unused-imports #-}+{-# OPTIONS_GHC -Wno-unused-matches #-}++module HaskellWorks.IO.Network.NamedPipe+  ( doesNamedPipeExist+  ) where++import           Data.Bool+import           Prelude (error)+import           System.IO (FilePath, IO)++#ifdef mingw32_HOST_OS+import qualified HaskellWorks.IO.Win32.NamedPipe as W32+#endif++doesNamedPipeExist :: FilePath -> IO Bool+doesNamedPipeExist path =+#ifdef mingw32_HOST_OS+  W32.waitNamedPipe path 1+#else+  error "doesNamedPipeExist may only be called on Windows"+#endif
+ src/HaskellWorks/IO/Network/Port.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE TypeApplications #-}++module HaskellWorks.IO.Network.Port+  ( randomPort,+    reserveRandomPort,+    portInUse,+  ) where++import           Control.Exception+import           Control.Monad                (Monad (..), MonadFail (..))+import           Control.Monad.IO.Class+import           Control.Monad.Trans.Resource+import           Data.Bool+import           Data.Either+import           Data.Function+import           Network.Socket++-- | Return a random available port on a specified host address+randomPort :: ()+  => MonadIO m+  => MonadFail m+  => HostAddress+  -> m PortNumber+randomPort hostAddress = do+  sock <- liftIO $ socket AF_INET Stream defaultProtocol+  -- Allow the port to be reused immediately after the socket is closed+  liftIO $ setSocketOption sock ReuseAddr 1+  liftIO $ bind sock $ SockAddrInet defaultPort hostAddress+  SockAddrInet port _ <- liftIO $ getSocketName sock+  liftIO $ close sock+  return port++reserveRandomPort :: ()+  => MonadFail m+  => MonadResource m+  => HostAddress+  -> m (ReleaseKey, PortNumber)+reserveRandomPort hostAddress = do+  sock <- liftIO $ socket AF_INET Stream defaultProtocol+  liftIO $ setSocketOption sock ReuseAddr 1+  liftIO $ bind sock $ SockAddrInet defaultPort hostAddress+  SockAddrInet port _ <- liftIO $ getSocketName sock+  releaseKey <- register $ close sock+  return (releaseKey, port)++-- | Check if a port is in use on a specified host address+portInUse :: ()+  => MonadIO m+  => HostAddress+  -> PortNumber+  -> m Bool+portInUse hostAddress pn = do+  sock <- liftIO $ socket AF_INET Stream defaultProtocol+  liftIO $ setSocketOption sock ReuseAddr 1+  result <- liftIO $ try @SomeException $ bind sock (SockAddrInet pn hostAddress)+  liftIO $ close sock+  return $ either (const False) (const True) result
+ src/HaskellWorks/IO/Network/Socket.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}++module HaskellWorks.IO.Network.Socket+  ( doesSocketExist,+    isPortOpen,+    canConnect,+    listenOn,+    allocateRandomPorts,+  ) where++import           Control.Exception  (IOException, handle)+import           Control.Monad+import           Data.Bool+import           Data.Function+import           Data.Functor+import           Data.Int+import           Data.Maybe+import           Network.Socket     (Family (AF_INET), SockAddr (..), Socket,+                                     SocketType (Stream))+import           Prelude            (fromIntegral)+import           System.IO          (FilePath, IO)+import           Text.Show          (show)++import qualified Network.Socket     as IO+import qualified System.Directory   as IO+import qualified UnliftIO.Exception as IO++-- | Check if a TCP port is open+isPortOpen :: Int -> IO Bool+isPortOpen port = do+  socketAddressInfos <- IO.getAddrInfo Nothing (Just "127.0.0.1") (Just (show port))+  case socketAddressInfos of+    socketAddressInfo:_ ->+      handle (return . const @Bool @IOException False) $+        canConnect (IO.addrAddress socketAddressInfo) $> True+    [] -> return False++-- | Check if it is possible to connect to a socket address+canConnect :: SockAddr -> IO ()+canConnect sockAddr = IO.bracket (IO.socket AF_INET Stream 6) IO.close' $ \sock -> do+  IO.connect sock sockAddr++-- | Open a socket at the specified port for listening+listenOn :: Int -> IO Socket+listenOn n = do+  sock <- IO.socket AF_INET Stream 0+  sockAddrInfo:_ <- IO.getAddrInfo Nothing (Just "127.0.0.1") (Just (show n))+  IO.setSocketOption sock IO.ReuseAddr 1+  IO.bind sock (IO.addrAddress sockAddrInfo)+  IO.listen sock 2+  return sock++doesSocketExist :: FilePath -> IO Bool+doesSocketExist = IO.doesFileExist+{-# INLINE doesSocketExist #-}++-- | Allocate the specified number of random ports+allocateRandomPorts :: Int -> IO [Int]+allocateRandomPorts n = do+  let hints = IO.defaultHints+        { IO.addrFlags = [IO.AI_PASSIVE]+        , IO.addrSocketType = IO.Stream+        }++  -- Create n sockets with randomly bound ports, grab the port numbers and close those ports+  addr:_ <- IO.getAddrInfo (Just hints) (Just "127.0.0.1") (Just "0")+  socks <- forM [1..n] $ \_ -> IO.socket (IO.addrFamily addr) (IO.addrSocketType addr) (IO.addrProtocol addr)+  forM_ socks $ \sock -> IO.bind sock (IO.addrAddress addr)+  ports <- forM socks IO.socketPort+  forM_ socks IO.close++  return $ fmap fromIntegral ports
+ src/HaskellWorks/IO/Process.hs view
@@ -0,0 +1,34 @@+module HaskellWorks.IO.Process+  ( maybeWaitForProcess,+    waitSecondsForProcess,+  ) where++import           Control.Concurrent       as IO+import           Control.Concurrent.Async as IO+import qualified Control.Exception        as IO+import           Data.Maybe+import           System.Exit+import           System.IO++import           Control.Applicative+import           Data.Function+import           Data.Functor+import           HaskellWorks.Error.Types+import           HaskellWorks.Prelude+import qualified System.Process           as IO+import           System.Process++maybeWaitForProcess :: ()+  => ProcessHandle+  -> IO (Maybe ExitCode)+maybeWaitForProcess hProcess =+  IO.catch (fmap Just (IO.waitForProcess hProcess)) $ \(_ :: AsyncCancelled) -> pure Nothing++waitSecondsForProcess :: ()+  => Int+  -> ProcessHandle+  -> IO (Either TimedOut (Maybe ExitCode))+waitSecondsForProcess seconds hProcess =+  IO.race+    (IO.threadDelay (seconds * 1000000) >> pure (TimedOut "Timed out waiting for process"))+    (maybeWaitForProcess hProcess)
+ src/HaskellWorks/IO/Win32/NamedPipe.hsc view
@@ -0,0 +1,71 @@+#include <fcntl.h>+#include <windows.h>++{-# LANGUAGE CPP                #-}+{-# LANGUAGE MultiWayIf         #-}++-- | For full details on the Windows named pipes API see+-- <https://docs.microsoft.com/en-us/windows/desktop/ipc/named-pipes>+--+module HaskellWorks.IO.Win32.NamedPipe+  ( -- ** waiting for named pipe instances+    waitNamedPipe,++    TimeOut,+    nMPWAIT_USE_DEFAULT_WAIT,+    nMPWAIT_WAIT_FOREVER,+  ) where++import Control.Applicative (pure)+import Data.Bool (Bool (..), otherwise)+import Data.Eq ((==))+import Data.Function (($))+import Data.String (String)+import Foreign.C.String (withCString)+import System.IO (IO)+import System.Win32.File+import System.Win32.Types hiding (try)++-- | Timeout in milliseconds.+--+-- * 'nMPWAIT_USE_DEFAULT_WAIT' indicates that the timeout value passed to+--   'createNamedPipe' should be used.+-- * 'nMPWAIT_WAIT_FOREVER' - 'waitNamedPipe' will block forever, until a named+--   pipe instance is available.+--+type TimeOut = DWORD+#{enum TimeOut,+ , nMPWAIT_USE_DEFAULT_WAIT = NMPWAIT_USE_DEFAULT_WAIT+ , nMPWAIT_WAIT_FOREVER     = NMPWAIT_WAIT_FOREVER+ }++-- | Wait until a named pipe instance is available.  If there is no instance at+-- hand before the timeout, it will error with 'ERROR_SEM_TIMEOUT', i.e.+-- @invalid argument (The semaphore timeout period has expired)@+--+-- It returns 'True' if there is an available instance, subsequent 'createFile'+-- might still fail, if another thread will take turn and connect before, or if+-- the other end shuts down the name pipe.+--+-- It returns 'False' if timeout fired.+--+waitNamedPipe :: String  -- ^ pipe name+              -> TimeOut -- ^ nTimeOut+              -> IO Bool+waitNamedPipe name timeout =+    withCString name $ \ c_name -> do+      r <- c_WaitNamedPipe c_name timeout+      e <- getLastError+      if | r                      -> pure r+         | e == eRROR_SEM_TIMEOUT -> pure False+         | otherwise              -> failWith "waitNamedPipe" e+++-- 'c_WaitNamedPipe' is a blocking call, hence the _safe_ import.+foreign import ccall safe "windows.h WaitNamedPipeA"+  c_WaitNamedPipe :: LPCSTR -- lpNamedPipeName+                  -> DWORD  -- nTimeOut+                  -> IO BOOL++eRROR_SEM_TIMEOUT :: ErrCode+eRROR_SEM_TIMEOUT = #const ERROR_SEM_TIMEOUT
+ src/HaskellWorks/Prelude.hs view
@@ -0,0 +1,205 @@+module HaskellWorks.Prelude+  ( Bool(..),+    Char(..),+    Maybe(..),+    Either(..),++    String,+    Text,+    ByteString,+    Int,+    Int8,+    Int16,+    Int32,+    Int64,+    Integer,+    Word,+    Word8,+    Word16,+    Word32,+    Word64,+    Float,+    Double,+    FilePath,+    Void,++    Eq(..),+    Ord(..),+    Num(..),+    Show(..),+    IsString(..),+    tshow,++    bool,+    const,++    absurd,+    vacuous,++    either,+    lefts,+    rights,+    isLeft,+    isRight,+    fromLeft,+    fromRight,++    maybe,+    isJust,+    isNothing,+    fromMaybe,+    listToMaybe,+    maybeToList,+    catMaybes,+    mapMaybe,++    fst,+    flip,+    snd,+    id,+    seq,+    curry,+    uncurry,+    ($!),+    ($),+    (&),+    not,+    otherwise,+    (&&),+    (||),+    (.),+    (</>),++    void,+    mapM_,+    forM,+    forM_,+    sequence_,+    (=<<),+    (>=>),+    (<=<),+    forever,+    join,+    msum,+    mfilter,+    filterM,+    foldM,+    foldM_,+    replicateM,+    replicateM_,+    guard,+    when,+    unless,+    liftM,+    liftM2,+    liftM3,+    liftM4,+    liftM5,+    ap,+    (<$!>),++    (<$>),++    (<**>),+    liftA,+    liftA3,+    optional,+    asum,++    for_,++    zip,+    zip3,+    zipWith,+    zipWith3,+    unzip,+    unzip3,++    Fractional(..),+    Floating(..),+    Integral(..),+    Read(..),+    Real(..),+    RealFrac(..),+    RealFloat(..),+    Ratio(..),+    Rational,+    fromIntegral,+    realToFrac,+    even,+    odd,+    numericEnumFrom,+    numericEnumFromThen,+    numericEnumFromTo,+    numericEnumFromThenTo,+    integralEnumFrom,+    integralEnumFromThen,+    integralEnumFromTo,+    integralEnumFromThenTo,+    numerator,+    denominator,+    (%),++    Monad(..),+    MonadFail(..),+    MonadPlus(..),+    Applicative(..),+    Alternative(..),+    Contravariant(..),+    Divisible(..),+    Functor(..),+    Bifunctor(..),+    Semigroup(..),+    Monoid(..),+    Foldable(..),+    Traversable(..),++    IO,++    CallStack,+    HasCallStack,+    withFrozenCallStack,++    Generic,++    IOException,+    IOError,+    SomeException(..),+  ) where++import           Control.Applicative+import           Control.Exception+import           Control.Monad+import           Data.Bifunctor+import           Data.Bool+import           Data.ByteString                      (ByteString)+import           Data.Char+import           Data.Either+import           Data.Eq+import           Data.Foldable+import           Data.Function+import           Data.Functor.Contravariant+import           Data.Functor.Contravariant.Divisible+import           Data.Int+import           Data.Maybe+import           Data.Monoid+import           Data.Ord+import           Data.Semigroup+import           Data.String+import           Data.Text                            (Text)+import           Data.Traversable+import           Data.Tuple+import           Data.Void+import           Data.Word+import           GHC.Base+import           GHC.Generics+import           GHC.Num+import           GHC.Real+import           GHC.Stack+import           Prelude+import           System.FilePath++import qualified Data.Text                            as T++tshow :: Show a => a -> Text+tshow = T.pack . show
+ src/HaskellWorks/Unsafe.hs view
@@ -0,0 +1,6 @@+module HaskellWorks.Unsafe+  ( error+  , undefined+  ) where++import           Prelude