grab-0.0.0.1: grab.cabal
cabal-version: 2.4
name: grab
version: 0.0.0.1
synopsis: Applicative non-linear consumption
category: Control
description:
== The Grab type
.
A grab consumes some portion (none, part, or all) of
its input @bag@, and returns a @residue@ consisting of
the unconsumed input, some monoidal @log@ (e.g. a list
of error messages), and some @desideratum@ (the object
of desire) produced from the consumed input, or
@Nothing@ if the grab failed.
.
> newtype Grab bag residue log desideratum =
> Grab (
> bag -> (residue, log, Maybe desideratum)
> )
.
Grabs are useful as parsers for inputs such as JSON
objects or lists of form parameters, where the input data
is not necessarily given linearly in the same order in
which we want to consume it.
.
== Applicative composition
.
A @Simple@ grab (where the @bag@ and @residue@ are the
same type) has an @Applicative@ instance.
.
> instance (bag ~ residue, Monoid log) =>
> Applicative (Grab bag residue log)
.
For example, we can create two simple list grabs, one that
grabs multiples of two, and the other that grabs multiples
of three:
.
> twos, threes :: Monoid log =>
> Control.Grab.Simple [Integer] log [Integer]
> twos = partition (Data.List.partition (\x -> mod x 2 == 0))
> threes = partition (Data.List.partition (\x -> mod x 3 == 0))
.
> λ> runGrabMaybe ((,) <$> twos @() <*> threes @()) [1..10]
> Just ([2,4,6,8,10],[3,9])
.
Notice that the second part of the resulting tuple contains only
the /odd/ multiples of three. Because @twos@ runs first, it
consumes @6@ before the @threes@ can get it.
.
== Pipeline composition
.
@a / b@ is a pipeline of two grabs, where the desideratum from
@a@ is the @bag@ for @b@.
.
> (/) :: Semigroup log
> => Grab bag residue log x
> -> Grab x _residue log desideratum
> -> Grab bag residue log desideratum
.
> λ> runGrabMaybe (twos @() / threes @()) [1..10]
> Just [6]
.
> λ> runGrabMaybe ((,) <$> (twos @() / threes @()) <*> threes @()) [1..10]
> Just ([6],[3,9])
homepage: https://github.com/typeclasses/grab
bug-reports: https://github.com/typeclasses/grab/issues
author: Chris Martin
maintainer: Chris Martin, Julie Moronuki
copyright: 2019 Typeclass Consulting, LLC
license: MIT
license-file: license.txt
tested-with: GHC==8.6.5
library
hs-source-dirs: src
default-language: Haskell2010
ghc-options: -fdefer-typed-holes
exposed-modules: Control.Grab
build-depends:
base ^>= 4.12.0.0
test-suite hedgehog
type: exitcode-stdio-1.0
default-language: Haskell2010
hs-source-dirs: test
main-is: hedgehog.hs
build-depends:
grab
, base ^>= 4.12.0.0
, hedgehog ^>= 0.6.1
-- This benchmark runs with a tightly limited stack size
-- to detect space leaks, as described by:
-- http://neilmitchell.blogspot.com/2015/09/detecting-space-leaks.html
--
-- Run it like this for a stack trace:
--
-- stack bench grab:space --profile --ba "+RTS -xc"
--
benchmark space
type: exitcode-stdio-1.0
hs-source-dirs: bench
main-is: space.hs
default-language: Haskell2010
ghc-options: "-with-rtsopts=-K1K"
build-depends:
grab
, base ^>= 4.12.0.0
benchmark time
type: exitcode-stdio-1.0
hs-source-dirs: bench
main-is: time.hs
default-language: Haskell2010
build-depends:
grab
, base ^>= 4.12.0.0
, criterion ^>= 1.5.5.0