Skip to content

Commit

Permalink
Deprecate MonadZero (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
kl0tl authored Nov 25, 2020
1 parent 185c084 commit 9132ec9
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 33 deletions.
23 changes: 23 additions & 0 deletions src/Control/Alternative.purs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module Control.Alternative
( class Alternative
, guard
, module Control.Alt
, module Control.Applicative
, module Control.Apply
Expand All @@ -12,6 +13,7 @@ import Control.Applicative (class Applicative, pure, liftA1, unless, when)
import Control.Apply (class Apply, apply, (*>), (<*), (<*>))
import Control.Plus (class Plus, empty)

import Data.Unit (Unit, unit)
import Data.Functor (class Functor, map, void, ($>), (<#>), (<$), (<$>))

-- | The `Alternative` type class has no members of its own; it just specifies
Expand All @@ -25,3 +27,24 @@ import Data.Functor (class Functor, map, void, ($>), (<#>), (<$), (<$>))
class (Applicative f, Plus f) <= Alternative f

instance alternativeArray :: Alternative Array

-- | Fail using `Plus` if a condition does not hold, or
-- | succeed using `Applicative` if it does.
-- |
-- | For example:
-- |
-- | ```purescript
-- | import Prelude
-- | import Control.Alternative (guard)
-- | import Data.Array ((..))
-- |
-- | factors :: Int -> Array Int
-- | factors n = do
-- | a <- 1..n
-- | b <- 1..n
-- | guard $ a * b == n
-- | pure a
-- | ```
guard :: forall m. Alternative m => Boolean -> m Unit
guard true = pure unit
guard false = empty
13 changes: 8 additions & 5 deletions src/Control/MonadPlus.purs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,23 @@ module Control.MonadPlus
) where

import Control.Alt (class Alt, alt, (<|>))
import Control.Alternative (class Alternative)
import Control.Alternative (class Alternative, guard)
import Control.Applicative (class Applicative, pure, liftA1, unless, when)
import Control.Apply (class Apply, apply, (*>), (<*), (<*>))
import Control.Bind (class Bind, bind, ifM, join, (<=<), (=<<), (>=>), (>>=))
import Control.Monad (class Monad, ap, liftM1)
import Control.MonadZero (class MonadZero, guard)
import Control.MonadZero (class MonadZero)
import Control.Plus (class Plus, empty)

import Data.Functor (class Functor, map, void, ($>), (<#>), (<$), (<$>))

-- | The `MonadPlus` type class has no members of its own but extends
-- | `MonadZero` with an additional law:
-- | The `MonadPlus` type class has no members of its own; it just specifies
-- | that the type has both `Monad` and `Alternative` instances.
-- |
-- | Types which have `MonadPlus` instances should also satisfy the following
-- | law:
-- |
-- | - Distributivity: `(x <|> y) >>= f == (x >>= f) <|> (y >>= f)`
class MonadZero m <= MonadPlus m
class (Monad m, Alternative m) <= MonadPlus m

instance monadPlusArray :: MonadPlus Array
42 changes: 14 additions & 28 deletions src/Control/MonadZero.purs
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
-- | This module is **deprecated** and will be removed in a future release.
-- |
-- | The annihilation law witnessed by `MonadZero` is trivially satisfied by
-- | lawful monads due to parametricity: while evaluating `empty >>= f`, the
-- | function `f` can’t ever be called, since that would require `empty` to
-- | produce a value, which means that `empty >>= f` must be the same as
-- | `empty >>= pure`, which by the monad laws is just `empty`.
-- |
-- | Use `Monad` and `Alternative` constraints instead.

module Control.MonadZero
( class MonadZero
, guard
, module Control.Alt
, module Control.Alternative
, module Control.Applicative
Expand All @@ -12,15 +21,16 @@ module Control.MonadZero
) where

import Control.Alt (class Alt, alt, (<|>))
import Control.Alternative (class Alternative)
import Control.Alternative (class Alternative, guard)
import Control.Applicative (class Applicative, pure, liftA1, unless, when)
import Control.Apply (class Apply, apply, (*>), (<*), (<*>))
import Control.Bind (class Bind, bind, ifM, join, (<=<), (=<<), (>=>), (>>=))
import Control.Monad (class Monad, ap, liftM1)
import Control.Plus (class Plus, empty)

import Data.Functor (class Functor, map, void, ($>), (<#>), (<$), (<$>))
import Data.Unit (Unit, unit)

import Prim.TypeError (class Warn, Text)

-- | The `MonadZero` type class has no members of its own; it just specifies
-- | that the type has both `Monad` and `Alternative` instances.
Expand All @@ -29,28 +39,4 @@ import Data.Unit (Unit, unit)
-- | laws:
-- |
-- | - Annihilation: `empty >>= f = empty`
class (Monad m, Alternative m) <= MonadZero m

instance monadZeroArray :: MonadZero Array

-- | Fail using `Plus` if a condition does not hold, or
-- | succeed using `Monad` if it does.
-- |
-- | For example:
-- |
-- | ```purescript
-- | import Prelude
-- | import Control.Monad (bind)
-- | import Control.MonadZero (guard)
-- | import Data.Array ((..))
-- |
-- | factors :: Int -> Array Int
-- | factors n = do
-- | a <- 1..n
-- | b <- 1..n
-- | guard $ a * b == n
-- | pure a
-- | ```
guard :: forall m. MonadZero m => Boolean -> m Unit
guard true = pure unit
guard false = empty
class (Monad m, Alternative m, Warn (Text "'MonadZero' is deprecated, use 'Monad' and 'Alternative' constraints instead")) <= MonadZero m

0 comments on commit 9132ec9

Please sign in to comment.