module LinearScan.Monad where


import Debug.Trace (trace, traceShow, traceShowId)
import qualified Prelude
import qualified Data.IntMap
import qualified Data.IntSet
import qualified Data.List
import qualified Data.Ord
import qualified Data.Functor.Identity
import qualified Hask.Utils

import qualified LinearScan.Applicative as Applicative
import qualified LinearScan.Functor as Functor
import qualified LinearScan.Seq as Seq


__ :: any
__ = Prelude.error "Logical or arity value used"

data Monad m =
   Build_Monad (Applicative.Applicative m) (() -> m -> m)

is_applicative :: (Monad a1) -> Applicative.Applicative a1
is_applicative monad =
  case monad of {
   Build_Monad is_applicative0 join0 -> is_applicative0}

join :: (Monad a1) -> a1 -> a1
join monad x =
  case monad of {
   Build_Monad is_applicative0 join0 -> join0 __ x}

bind :: (Monad a1) -> (a2 -> a1) -> a1 -> a1
bind h f =
  (Prelude..) (join h)
    (Functor.fmap (Applicative.is_functor (is_applicative h)) f)

return_ :: (Monad a1) -> a2 -> a1
return_ h =
  Applicative.pure (is_applicative h)

when :: (Monad a1) -> Prelude.Bool -> a1 -> a1
when h b x =
  case b of {
   Prelude.True -> x;
   Prelude.False -> return_ h ()}

unless :: (Monad a1) -> Prelude.Bool -> a1 -> a1
unless h b x =
  case Prelude.not b of {
   Prelude.True -> x;
   Prelude.False -> return_ h ()}

mapM :: (Applicative.Applicative a1) -> (a2 -> a1) -> ([] a2) -> a1
mapM h f l =
  case l of {
   [] -> Applicative.pure h [];
   (:) x xs -> Applicative.liftA2 h (\x0 x1 -> (:) x0 x1) (f x) (mapM h f xs)}

mapM_ :: (Monad a1) -> (a2 -> a1) -> ([] a2) -> a1
mapM_ h f l =
  case l of {
   [] -> Applicative.pure (is_applicative h) ();
   (:) x xs -> bind h (\x0 -> mapM_ h f xs) (f x)}

forM_ :: (Monad a1) -> ([] a2) -> (a2 -> a1) -> a1
forM_ h l f =
  mapM_ h f l

foldM :: (Monad a1) -> (a2 -> a3 -> a1) -> a2 -> ([] a3) -> a1
foldM h f s l =
  case l of {
   [] -> Applicative.pure (is_applicative h) s;
   (:) y ys -> bind h (\x -> foldM h f x ys) (f s y)}

forFoldM :: (Monad a1) -> a2 -> ([] a3) -> (a2 -> a3 -> a1) -> a1
forFoldM h s l f =
  foldM h f s l

foldrM :: (Monad a1) -> (a3 -> a2 -> a1) -> a2 -> ([] a3) -> a1
foldrM h f s l =
  case l of {
   [] -> Applicative.pure (is_applicative h) s;
   (:) y ys -> bind h (f y) (foldrM h f s ys)}

forFoldrM :: (Monad a1) -> a2 -> ([] a3) -> (a3 -> a2 -> a1) -> a1
forFoldrM h s l f =
  foldrM h f s l

concatMapM :: (Applicative.Applicative a1) -> (a2 -> a1) -> ([] a2) -> a1
concatMapM h f l =
  Functor.fmap (Applicative.is_functor h) Seq.flatten (mapM h f l)