{- |
Module      : Language.Egison.MList
Licence     : MIT

This module provides definition and utility functions for monadic list.
-}

module Language.Egison.MList
  ( MList (..)
  , fromList
  , fromSeq
  , fromMList
  , msingleton
  , mfoldr
  , mappend
  , mconcat
  , mmap
  , mfor
  , mAny
  ) where

import           Data.Sequence (Seq)
import           Prelude       hiding (mappend, mconcat)

data MList m a = MNil | MCons a (m (MList m a))

instance Show a => Show (MList m a) where
  show :: MList m a -> String
show MList m a
MNil        = String
"MNil"
  show (MCons a
x m (MList m a)
_) = String
"(MCons " String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" ...)"

fromList :: Monad m => [a] -> MList m a
fromList :: [a] -> MList m a
fromList = (a -> MList m a -> MList m a) -> MList m a -> [a] -> MList m a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> MList m a -> MList m a
forall (m :: * -> *) a. Monad m => a -> MList m a -> MList m a
f MList m a
forall (m :: * -> *) a. MList m a
MNil
 where f :: a -> MList m a -> MList m a
f a
x MList m a
xs = a -> m (MList m a) -> MList m a
forall (m :: * -> *) a. a -> m (MList m a) -> MList m a
MCons a
x (m (MList m a) -> MList m a) -> m (MList m a) -> MList m a
forall a b. (a -> b) -> a -> b
$ MList m a -> m (MList m a)
forall (m :: * -> *) a. Monad m => a -> m a
return MList m a
xs

fromSeq :: Monad m => Seq a -> MList m a
fromSeq :: Seq a -> MList m a
fromSeq = (a -> MList m a -> MList m a) -> MList m a -> Seq a -> MList m a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> MList m a -> MList m a
forall (m :: * -> *) a. Monad m => a -> MList m a -> MList m a
f MList m a
forall (m :: * -> *) a. MList m a
MNil
 where f :: a -> MList m a -> MList m a
f a
x MList m a
xs = a -> m (MList m a) -> MList m a
forall (m :: * -> *) a. a -> m (MList m a) -> MList m a
MCons a
x (m (MList m a) -> MList m a) -> m (MList m a) -> MList m a
forall a b. (a -> b) -> a -> b
$ MList m a -> m (MList m a)
forall (m :: * -> *) a. Monad m => a -> m a
return MList m a
xs

fromMList :: Monad m => MList m a -> m [a]
fromMList :: MList m a -> m [a]
fromMList = (a -> m [a] -> m [a]) -> m [a] -> MList m a -> m [a]
forall (m :: * -> *) a b.
Monad m =>
(a -> m b -> m b) -> m b -> MList m a -> m b
mfoldr a -> m [a] -> m [a]
forall (f :: * -> *) a. Functor f => a -> f [a] -> f [a]
f (m [a] -> MList m a -> m [a]) -> m [a] -> MList m a -> m [a]
forall a b. (a -> b) -> a -> b
$ [a] -> m [a]
forall (m :: * -> *) a. Monad m => a -> m a
return []
  where f :: a -> f [a] -> f [a]
f a
x f [a]
xs = (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:) ([a] -> [a]) -> f [a] -> f [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f [a]
xs

msingleton :: Monad m => a -> MList m a
msingleton :: a -> MList m a
msingleton = (a -> m (MList m a) -> MList m a)
-> m (MList m a) -> a -> MList m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> m (MList m a) -> MList m a
forall (m :: * -> *) a. a -> m (MList m a) -> MList m a
MCons (m (MList m a) -> a -> MList m a)
-> m (MList m a) -> a -> MList m a
forall a b. (a -> b) -> a -> b
$ MList m a -> m (MList m a)
forall (m :: * -> *) a. Monad m => a -> m a
return MList m a
forall (m :: * -> *) a. MList m a
MNil

mfoldr :: Monad m => (a -> m b -> m b) -> m b -> MList m a -> m b
mfoldr :: (a -> m b -> m b) -> m b -> MList m a -> m b
mfoldr a -> m b -> m b
_ m b
init MList m a
MNil         = m b
init
mfoldr a -> m b -> m b
f m b
init (MCons a
x m (MList m a)
xs) = a -> m b -> m b
f a
x (m (MList m a)
xs m (MList m a) -> (MList m a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (a -> m b -> m b) -> m b -> MList m a -> m b
forall (m :: * -> *) a b.
Monad m =>
(a -> m b -> m b) -> m b -> MList m a -> m b
mfoldr a -> m b -> m b
f m b
init)

mappend :: Monad m => MList m a -> m (MList m a) -> m (MList m a)
mappend :: MList m a -> m (MList m a) -> m (MList m a)
mappend MList m a
xs m (MList m a)
ys = (a -> m (MList m a) -> m (MList m a))
-> m (MList m a) -> MList m a -> m (MList m a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b -> m b) -> m b -> MList m a -> m b
mfoldr ((MList m a -> m (MList m a)
forall (m :: * -> *) a. Monad m => a -> m a
return (MList m a -> m (MList m a))
-> (m (MList m a) -> MList m a) -> m (MList m a) -> m (MList m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((m (MList m a) -> MList m a) -> m (MList m a) -> m (MList m a))
-> (a -> m (MList m a) -> MList m a)
-> a
-> m (MList m a)
-> m (MList m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m (MList m a) -> MList m a
forall (m :: * -> *) a. a -> m (MList m a) -> MList m a
MCons) m (MList m a)
ys MList m a
xs

mconcat :: Monad m => MList m (MList m a) -> m (MList m a)
mconcat :: MList m (MList m a) -> m (MList m a)
mconcat = (MList m a -> m (MList m a) -> m (MList m a))
-> m (MList m a) -> MList m (MList m a) -> m (MList m a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b -> m b) -> m b -> MList m a -> m b
mfoldr MList m a -> m (MList m a) -> m (MList m a)
forall (m :: * -> *) a.
Monad m =>
MList m a -> m (MList m a) -> m (MList m a)
mappend (m (MList m a) -> MList m (MList m a) -> m (MList m a))
-> m (MList m a) -> MList m (MList m a) -> m (MList m a)
forall a b. (a -> b) -> a -> b
$ MList m a -> m (MList m a)
forall (m :: * -> *) a. Monad m => a -> m a
return MList m a
forall (m :: * -> *) a. MList m a
MNil

mmap :: Monad m => (a -> m b) -> MList m a -> m (MList m b)
mmap :: (a -> m b) -> MList m a -> m (MList m b)
mmap a -> m b
f = (a -> m (MList m b) -> m (MList m b))
-> m (MList m b) -> MList m a -> m (MList m b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b -> m b) -> m b -> MList m a -> m b
mfoldr a -> m (MList m b) -> m (MList m b)
forall (m :: * -> *). a -> m (MList m b) -> m (MList m b)
g (m (MList m b) -> MList m a -> m (MList m b))
-> m (MList m b) -> MList m a -> m (MList m b)
forall a b. (a -> b) -> a -> b
$ MList m b -> m (MList m b)
forall (m :: * -> *) a. Monad m => a -> m a
return MList m b
forall (m :: * -> *) a. MList m a
MNil
  where g :: a -> m (MList m b) -> m (MList m b)
g a
x m (MList m b)
xs = (b -> m (MList m b) -> MList m b)
-> m (MList m b) -> b -> MList m b
forall a b c. (a -> b -> c) -> b -> a -> c
flip b -> m (MList m b) -> MList m b
forall (m :: * -> *) a. a -> m (MList m a) -> MList m a
MCons m (MList m b)
xs (b -> MList m b) -> m b -> m (MList m b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> m b
f a
x

mfor :: Monad m => MList m a -> (a -> m b) -> m (MList m b)
mfor :: MList m a -> (a -> m b) -> m (MList m b)
mfor = ((a -> m b) -> MList m a -> m (MList m b))
-> MList m a -> (a -> m b) -> m (MList m b)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> m b) -> MList m a -> m (MList m b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> MList m a -> m (MList m b)
mmap

mAny :: Monad m => (a -> m Bool) -> MList m a -> m Bool
mAny :: (a -> m Bool) -> MList m a -> m Bool
mAny a -> m Bool
_ MList m a
MNil = Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
mAny a -> m Bool
p (MCons a
x m (MList m a)
xs) = do
  Bool
b <- a -> m Bool
p a
x
  if Bool
b
   then Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
   else do MList m a
xs' <- m (MList m a)
xs
           (a -> m Bool) -> MList m a -> m Bool
forall (m :: * -> *) a.
Monad m =>
(a -> m Bool) -> MList m a -> m Bool
mAny a -> m Bool
p MList m a
xs'