{-# LANGUAGE CPP #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE UndecidableInstances #-} module ClassyPrelude.Classes where import CorePrelude import qualified Prelude import qualified Data.List as List import qualified Data.List.NonEmpty as NonEmpty import Data.List.NonEmpty (NonEmpty) import qualified Data.ByteString as ByteString import qualified Data.ByteString.Char8 as ByteString8 import qualified Data.ByteString.Lazy as LByteString import qualified Data.Text as Text import qualified Data.Text.IO as Text import qualified Data.Text.Lazy as LText import qualified Data.Text.Lazy.IO as LText import qualified Filesystem.Path.CurrentOS as FilePath import qualified Data.Vector as Vector import qualified Data.Vector.Unboxed as UVector import qualified Data.Sequence as Seq import Data.MonoTraversable import Data.Sequences (fromStrict, IsSequence) import Control.Monad (liftM) import System.IO (Handle) import qualified System.IO class IsSequence a => IOData a where readFile :: MonadIO m => FilePath -> m a writeFile :: MonadIO m => FilePath -> a -> m () getLine :: MonadIO m => m a hGetContents :: MonadIO m => Handle -> m a hGetLine :: MonadIO m => Handle -> m a hPut :: MonadIO m => Handle -> a -> m () hPutStrLn :: MonadIO m => Handle -> a -> m () hGetChunk :: MonadIO m => Handle -> m a instance IOData ByteString where readFile = liftIO . ByteString.readFile . FilePath.encodeString writeFile fp = liftIO . ByteString.writeFile (FilePath.encodeString fp) getLine = liftIO ByteString.getLine hGetContents = liftIO . ByteString.hGetContents hGetLine = liftIO . ByteString.hGetLine hPut h = liftIO . ByteString.hPut h hPutStrLn h = liftIO . ByteString8.hPutStrLn h hGetChunk = liftIO . flip ByteString.hGetSome 4096 instance IOData LByteString where readFile = liftIO . LByteString.readFile . FilePath.encodeString writeFile fp = liftIO . LByteString.writeFile (FilePath.encodeString fp) getLine = liftM fromStrict (liftIO ByteString.getLine) hGetContents = liftIO . LByteString.hGetContents hGetLine = liftM fromStrict . liftIO . ByteString.hGetLine hPut h = liftIO . LByteString.hPut h hPutStrLn h lbs = liftIO $ do LByteString.hPutStr h lbs ByteString8.hPutStrLn h ByteString.empty hGetChunk = liftM fromStrict . hGetChunk instance IOData Text where readFile = liftIO . Text.readFile . FilePath.encodeString writeFile fp = liftIO . Text.writeFile (FilePath.encodeString fp) getLine = liftIO Text.getLine hGetContents = liftIO . Text.hGetContents hGetLine = liftIO . Text.hGetLine hPut h = liftIO . Text.hPutStr h hPutStrLn h = liftIO . Text.hPutStrLn h #if MIN_VERSION_text(0, 11, 3) hGetChunk = liftIO . Text.hGetChunk #else -- Dangerously inefficient! hGetChunk = liftIO . liftM Text.singleton . System.IO.hGetChar #endif instance IOData LText where readFile = liftIO . LText.readFile . FilePath.encodeString writeFile fp = liftIO . LText.writeFile (FilePath.encodeString fp) getLine = liftIO LText.getLine hGetContents = liftIO . LText.hGetContents hGetLine = liftIO . LText.hGetLine hPut h = liftIO . LText.hPutStr h hPutStrLn h = liftIO . LText.hPutStrLn h hGetChunk = liftM fromStrict . hGetChunk instance (Char ~ c) => IOData [c] where readFile = liftIO . Prelude.readFile . FilePath.encodeString writeFile fp = liftIO . Prelude.writeFile (FilePath.encodeString fp) getLine = liftIO Prelude.getLine hGetContents = liftIO . System.IO.hGetContents hGetLine = liftIO . System.IO.hGetLine hPut h = liftIO . System.IO.hPutStr h hPutStrLn h = liftIO . System.IO.hPutStrLn h hGetChunk = liftM Text.unpack . hGetChunk class CanZip c1 c2 withRes t | c1 -> c2 withRes t , c2 -> c1 where zip :: c1 -> c2 -> t (Element c1, Element c2) unzip :: t (Element c1, Element c2) -> (c1, c2) zipWith :: (Element c1 -> Element c2 -> Element withRes) -> c1 -> c2 -> withRes instance CanZip [a] [b] [c] [] where zip = List.zip unzip = List.unzip zipWith = List.zipWith instance CanZip (NonEmpty a) (NonEmpty b) (NonEmpty c) NonEmpty where zip = NonEmpty.zip unzip = NonEmpty.unzip zipWith = NonEmpty.zipWith instance CanZip (Vector a) (Vector b) (Vector c) Vector where zip = Vector.zip unzip = Vector.unzip zipWith = Vector.zipWith instance (Unbox a, Unbox b, Unbox c) => CanZip (UVector a) (UVector b) (UVector c) UVector where zip = UVector.zip unzip = UVector.unzip zipWith = UVector.zipWith instance CanZip (Seq a) (Seq b) (Seq c) Seq where zip = Seq.zip unzip = (\(a, b) -> (Seq.fromList a, Seq.fromList b)) . List.unzip . otoList zipWith = Seq.zipWith instance CanZip ByteString ByteString [a] [] where zip = ByteString.zip unzip = ByteString.unzip zipWith = ByteString.zipWith instance CanZip LByteString LByteString [a] [] where zip = LByteString.zip unzip = LByteString.unzip zipWith = LByteString.zipWith instance CanZip Text Text Text [] where zip = Text.zip unzip = (Text.pack *** Text.pack) . List.unzip zipWith = Text.zipWith instance CanZip LText LText LText [] where zip = LText.zip unzip = (LText.pack *** LText.pack) . List.unzip zipWith = LText.zipWith class CanZip3 t a b c d | t -> a b c d where zip3 :: t a -> t b -> t c -> t (a, b, c) unzip3 :: t (a, b, c) -> (t a, t b, t c) zipWith3 :: (a -> b -> c -> d) -> t a -> t b -> t c -> t d instance CanZip3 [] a b c d where zip3 = List.zip3 unzip3 = List.unzip3 zipWith3 = List.zipWith3 instance CanZip3 Vector a b c d where zip3 = Vector.zip3 unzip3 = Vector.unzip3 zipWith3 = Vector.zipWith3 instance (Unbox a, Unbox b, Unbox c, Unbox d) => CanZip3 UVector a b c d where zip3 = UVector.zip3 unzip3 = UVector.unzip3 zipWith3 = UVector.zipWith3 instance CanZip3 Seq a b c d where zip3 = Seq.zip3 unzip3 = (\(a, b, c) -> (Seq.fromList a, Seq.fromList b, Seq.fromList c)) . List.unzip3 . otoList zipWith3 = Seq.zipWith3 class CanZip4 t a b c d e | t -> a b c d e where zip4 :: t a -> t b -> t c -> t d -> t (a, b, c, d) unzip4 :: t (a, b, c, d) -> (t a, t b, t c, t d) zipWith4 :: (a -> b -> c -> d -> e) -> t a -> t b -> t c -> t d -> t e instance CanZip4 [] a b c d e where zip4 = List.zip4 unzip4 = List.unzip4 zipWith4 = List.zipWith4 instance CanZip4 Vector a b c d e where zip4 = Vector.zip4 unzip4 = Vector.unzip4 zipWith4 = Vector.zipWith4 instance (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => CanZip4 UVector a b c d e where zip4 = UVector.zip4 unzip4 = UVector.unzip4 zipWith4 = UVector.zipWith4 instance CanZip4 Seq a b c d e where zip4 = Seq.zip4 unzip4 = (\(a, b, c, d) -> (Seq.fromList a, Seq.fromList b, Seq.fromList c, Seq.fromList d)) . List.unzip4 . otoList zipWith4 = Seq.zipWith4 class CanZip5 t a b c d e f | t -> a b c d e f where zip5 :: t a -> t b -> t c -> t d -> t e -> t (a, b, c, d, e) unzip5 :: t (a, b, c, d, e) -> (t a, t b, t c, t d, t e) zipWith5 :: (a -> b -> c -> d -> e -> f) -> t a -> t b -> t c -> t d -> t e -> t f instance CanZip5 [] a b c d e f where zip5 = List.zip5 unzip5 = List.unzip5 zipWith5 = List.zipWith5 instance CanZip5 Vector a b c d e f where zip5 = Vector.zip5 unzip5 = Vector.unzip5 zipWith5 = Vector.zipWith5 instance (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => CanZip5 UVector a b c d e f where zip5 = UVector.zip5 unzip5 = UVector.unzip5 zipWith5 = UVector.zipWith5 class CanZip6 t a b c d e f g | t -> a b c d e f g where zip6 :: t a -> t b -> t c -> t d -> t e -> t f -> t (a, b, c, d, e, f) unzip6 :: t (a, b, c, d, e, f) -> (t a, t b, t c, t d, t e, t f) zipWith6 :: (a -> b -> c -> d -> e -> f -> g) -> t a -> t b -> t c -> t d -> t e -> t f -> t g instance CanZip6 [] a b c d e f g where zip6 = List.zip6 unzip6 = List.unzip6 zipWith6 = List.zipWith6 instance CanZip6 Vector a b c d e f g where zip6 = Vector.zip6 unzip6 = Vector.unzip6 zipWith6 = Vector.zipWith6 instance (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f, Unbox g) => CanZip6 UVector a b c d e f g where zip6 = UVector.zip6 unzip6 = UVector.unzip6 zipWith6 = UVector.zipWith6 class CanZip7 t a b c d e f g h | t -> a b c d e f g h where zip7 :: t a -> t b -> t c -> t d -> t e -> t f -> t g -> t (a, b, c, d, e, f, g) unzip7 :: t (a, b, c, d, e, f, g) -> (t a, t b, t c, t d, t e, t f, t g) zipWith7 :: (a -> b -> c -> d -> e -> f -> g -> h) -> t a -> t b -> t c -> t d -> t e -> t f -> t g -> t h instance CanZip7 [] a b c d e f g h where zip7 = List.zip7 unzip7 = List.unzip7 zipWith7 = List.zipWith7