packages feed

vary 0.1.0.0 → 0.1.0.1

raw patch · 2 files changed

+9/−127 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

src/Vary.hs view
@@ -70,10 +70,14 @@ -- -- >>> import Vary (Vary, (:|)) -- >>> import qualified Vary+--+-- You probably often want to use it together with the "Vary.Either" module:+-- >>> import Vary.Either (VEither(VLeft, VRight))+-- >>> import qualified Vary.VEither as VEither -- --- And for many functions, it is useful or outright necessary to enable the following extensions:+-- And for many functions, it is useful (and sometimes outright necessary) to enable the following extensions: ----- >>> :set -XGHC2021+-- >>> :set -XGHC2021 -- Of these, Vary uses: TypeApplications, TypeOperators, FlexibleContexts -- >>> :set -XDataKinds -- -- Finally, some example snippets in this module make use of 'Data.Function.&', the left-to-right function application operator.@@ -84,129 +88,7 @@   == Motivating Example - Say we are writing an image thumbnailing service.-- * Given an image URL-- * We attempt to download it.--     * This can fail, because the URL is incorrect;--     * Or the URL /is/ correct but the server could not be reached (in which case we want to re-try later);--     * Or the server /could/ be reached, but downloading took longer than a set time limit.-- * We pass it to a thumbnailing program.--     * This can fail, because the downloaded file might turn out actually not to be a valid image file (PNG or JPG);--     * Or even if the downloaded file /is/ an image, it might have a much too high resolution to attempt to read;--- The first instinct of many Haskell programmers is to write dedicated sum types for these errors like so:-->>> import Data.Bifunctor (first)->>> data Image = Image->>>->>> data DownloaderError = IncorrectUrl | ServerUnreachable | DownloadingTimedOut deriving (Eq, Ord, Show)->>> data ThumbnailError = NotAnImage | TooBigImage deriving (Eq, Ord, Show)->>>->>> download = undefined :: String -> Either DownloaderError Image->>>->>> thumbnail = undefined :: Image -> Either ThumbnailError Image--But if we try to plainly combine these two functions, we get a compiler error:-->>> :{-  thumbnailService url = do-    image <- download url-    thumbnail <- thumbnail image-    pure thumbnail-:}-...-...• Couldn't match type ‘ThumbnailError’ with ‘DownloaderError’-...--We could \'solve\' this problem by adding yet another manual error type:-->>> data ThumbnailServiceError = DownloaderError DownloaderError | ThumbnailError ThumbnailError deriving (Eq, Ord, Show)->>> :{-  thumbnailService :: String -> Either ThumbnailServiceError Image-  thumbnailService url = do-    image <- first DownloaderError $ download url-    thumb <- first ThumbnailError $ thumbnail image-    pure thumb-:}--This \'works\', although already we can see that we're doing a lot of manual ceremony to pass the errors around.--And wait! We wanted to re-try in the case of a `ServerUnreachable` error!-->>> waitAndRetry = undefined :: Word -> (() -> a)  -> a->>> :{-  thumbnailService :: String -> Either ThumbnailServiceError Image-  thumbnailService url = -    case download url of-      Left ServerUnreachable -> waitAndRetry 10 (\_ -> thumbnailService url) -      Left other -> Left (DownloaderError other)-      Right image -> do-        thumb <- first ThumbnailError $ thumbnail image-        pure thumb-:}--We now see:--- Even inside @thumbnailService@ there now is quite a bit of ceremony -  w.r.t. wrapping,unwrapping and mapping between error types.-- Callers will be asked to pattern match on the @ServerUnreachable@ error case,-  even though that case will already be handled inside the @thumbnailService@ function itself!-- Imagine what happens when using this small function in a bigger system with many more errors!-  Do you keep defining more and more wrapper types for various combinations of errors?--==== There is a better way!--With the `Vary` and related `Vary.VEither.VEither` types, you can mix and match individual errors (or other types) at the places they are used.--- No more wrapper type definitions!-- Handing an error makes it go away from the outcome type!-->>> import Vary.VEither (VEither)->>> import qualified Vary.VEither as VEither->>> data Image = Image deriving(Show)->>>->>> data IncorrectUrl = IncorrectUrl deriving (Eq, Ord, Show)->>> data ServerUnreachable = ServerUnreachable deriving (Eq, Ord, Show)->>> data DownloadingTimedOut = DownloadingTimedOut deriving (Eq, Ord, Show)->>>->>> data NotAnImage = NotAnImage deriving (Eq, Ord, Show)->>> data TooBigImage = TooBigImage deriving (Eq, Ord, Show)->>>->>> download = undefined :: (ServerUnreachable :| err, IncorrectUrl :| err) => String -> VEither err Image->>> thumbnail = undefined :: (NotAnImage :| err, TooBigImage :| err) => Image -> VEither err Image->>>->>> waitAndRetry = undefined :: Word -> (() -> a)  -> a->>>--Here is the version without the retry:-->>> :{-thumbnailService :: String -> VEither [ServerUnreachable, IncorrectUrl, NotAnImage, TooBigImage] Image-thumbnailService url = do-  image <- download url-  thumb <- thumbnail image-  pure thumb-:}--And here is all that needed to change to have a retry:-->>> :{-thumbnailService :: String -> VEither [IncorrectUrl, NotAnImage, TooBigImage] Image-thumbnailService url = do-  image <- download url -           & VEither.onLeft (\ServerUnreachable -> waitAndRetry 10 (\_ -> thumbnailService url)) id-  thumb <- thumbnail image-  pure thumb-:}+A longer example on why you would want to use Vary [can be found in the package README on GitHub](https://github.com/qqwy/haskell-vary#readme)  -} 
vary.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.2.+-- This file has been generated from package.yaml by hpack version 0.36.0. -- -- see: https://github.com/sol/hpack  name:           vary-version:        0.1.0.0+version:        0.1.0.1 synopsis:       Vary: Friendly and fast polymorphic variants (open unions/coproducts/extensible sums) description:    Vary: Friendly and fast Variant types for Haskell                 .