{-# OPTIONS --type-in-type #-}

open import NeilPrelude
open import List
open import Bool

module MonadPlus (M : Set  Set)

       (_>>=_  : {A B : Set}  M A  (A  M B)  M B)
       (return : {A : Set}  A  M A)
       (plus   : {A : Set}  M A  M A  M A)
       (zero   : {A : Set}  M A)

where

import Monad
open Monad M _>>=_ return public

mplus : {A : Set}  M A  M A  M A
mplus = plus

mzero : {A : Set}  M A
mzero = zero

msum : {A : Set}  List (M A)  M A
msum = foldl mplus mzero

mfilter : {A : Set}  (A  Bool)  M A  M A
mfilter p ma = ma >>= λ a  if p a then return a else mzero

guard : Bool  M Unit
guard false = mzero
guard true  = return unit