laziness in IO
S.M.Kahrs
S.M.Kahrs@ukc.ac.uk
Wed, 08 Jan 2003 18:49:00 +0000
This is a multipart MIME message.
--==_Exmh_-17196631560
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
I don't think you can do what you want to using standard lists,
not without some dirty trickery...
But you can define a datatype for such a purpose which would essentially
have to put the tail into the Monad.
Disadvantage: you would have to redo lots of the list stuff yourself.
I had once started writing such a module, it's attached...
With this you can write your program as follows:
main =3D
do xs <- getStrings
putStrLn(headML xs)
getStrings =3D
do { x <- getLine; if x=3D=3D"stop" then return NIL
else return (x:<:getStrings)
}
So, this uses headML instead of head, NIL instead of [], etc.
But the things that makes everything work is the different cons-operator,=
the :<: which allows the list tail to still sit in some monad.
Hope this helps
Stefan Kahrs
--==_Exmh_-17196631560
Content-Type: text/plain ; name="ListForMonad.hs"; charset=us-ascii
Content-Description: ListForMonad.hs
Content-Disposition: attachment; filename="ListForMonad.hs"
Content-Transfer-Encoding: quoted-printable
module ListForMonad where
import Monad
data Mlist m a =3D NIL | a :<: m (Mlist m a)
nullML :: Mlist m a -> Bool
nullML NIL =3D True
nullML _ =3D False
(<:) :: Monad m =3D> a -> m (Mlist m a) -> m (Mlist m a)
x <: ms =3D return (x :<: ms)
(+<+) :: Monad m =3D> Mlist m a -> m (Mlist m a) -> m (Mlist m a)
xs +<+ ms =3D foldrML (<:) ms xs
(!<!) :: Monad m =3D> Mlist m a -> Int -> m a
NIL !<! _ =3D error "index out of bounds"
(x :<: ms) !<! 0 =3D return x
(_ :<: ms) !<! n =3D ms >>=3D (!<! (n-1))
lengthML :: Monad m =3D> Mlist m a -> m Int
lengthML NIL =3D return 0
lengthML (_ :<: ms) =3D liftM (+1) (ms >>=3D lengthML)
headML :: Mlist m a -> a
headML (x :<: _ ) =3D x
headML NIL =3D error "head of empty list"
lastML :: Monad m =3D> Mlist m a -> m a
lastML (x :<: ms) =3D
do xs<-ms
case xs of NIL -> return x
p -> lastML p
lastML NIL =3D error "last of empty list"
tailML :: Mlist m a -> m (Mlist m a)
tailML (_ :<: ms) =3D ms
tailML NIL =3D error "tail of empty list"
initML :: Monad m =3D> Mlist m a -> m (Mlist m a)
initML NIL =3D error "init of empty list"
initML (x :<: ms) =3D
do xs<-ms
case xs of NIL -> return NIL
p -> return (x :<: initML p)
replicateML :: Monad m =3D> Int -> m a -> m (Mlist m a)
replicateML n a =3D liftM (takeML n) (repeatML a)
repeatML :: Monad m =3D> m a -> m (Mlist m a)
repeatML action =3D xs
where
xs =3D do { r<-action; return (r :<: xs) }
takeML :: Monad m =3D> Int -> Mlist m a -> Mlist m a
takeML _ NIL =3D NIL
takeML 0 _ =3D NIL
takeML n (x:<:ms) =3D x :<: (liftM (takeML (n-1)) ms)
dropML :: Monad m =3D> Int -> Mlist m a -> m(Mlist m a)
dropML 0 xs =3D return xs
dropML _ NIL =3D return NIL
dropML n (x:<:ms) =3D ms >>=3D dropML (n-1)
splitAtML :: Monad m =3D> Int -> Mlist m a -> m (Mlist m a, m(Mlist m a))=
splitAtML 0 xs =3D return (NIL, return xs)
splitAtML n NIL =3D return (NIL, return NIL)
splitAtML n (x:<: ms) =3D
do m<-ms
(as,ns)<-splitAtML (n-1) m
return (x :<: return as,ns)
reverseML :: Monad m =3D> Mlist m a -> m (Mlist m a)
reverseML ms =3D
do xs <- mlToList ms
foldr (<:) (return NIL) (reverse xs)
zipML :: Monad m =3D> Mlist m a -> Mlist m b -> Mlist m (a,b) =
zipML (x:<:ms) (y:<:ns) =3D (x,y) :<: do { xs<-ms; ys<-ns; return(zipML x=
s ys) }
zipML _ _ =3D NIL
unzipML :: Monad m =3D> Mlist m (a,b) -> (Mlist m a,Mlist m b)
unzipML xs =3D (fmap fst xs,fmap snd xs) {- note: re-evaluation -}
instance Monad m =3D> Functor (Mlist m) where
fmap f NIL =3D NIL
fmap f (x:<:ms) =3D f x :<: (liftM (fmap f) ms)
mlToList :: Monad m =3D> Mlist m a -> m [a]
mlToList NIL =3D return []
mlToList (x :<: ms) =3D liftM (x:)(ms >>=3D mlToList)
foldrML :: Monad m =3D> (a -> m b -> m b) -> m b -> Mlist m a -> m b
foldrML f n NIL =3D n
foldrML f n (x :<: ms) =3D f x (ms >>=3D foldrML f n)
blift :: Monad m =3D> (a->b->b) -> (a-> m b -> m b)
blift f x act =3D liftM (f x) act
(&<&) :: Monad m =3D> Bool -> m Bool -> m Bool
True &<& xs =3D xs
False &<& _ =3D return False
(|<|) :: Monad m =3D> Bool -> m Bool -> m Bool
True |<| xs =3D return True
False |<| xs =3D xs
andML :: Monad m =3D> Mlist m Bool -> m Bool
andML xs =3D foldrML (&<&) (return True) xs
orML :: Monad m =3D> Mlist m Bool -> m Bool
orML xs =3D foldrML (|<|) (return False) xs
anyML :: Monad m =3D> (a->Bool) -> Mlist m a -> m(Bool)
anyML p xs =3D orML $ fmap p xs
allML :: Monad m =3D> (a->Bool) -> Mlist m a -> m(Bool)
allML p xs =3D andML $ fmap p xs
sumML :: (Monad m,Num a) =3D> Mlist m a -> m a
sumML NIL =3D return 0
sumML (x:<:ms) =3D liftM (+x) (ms>>=3D sumML)
productML :: (Monad m,Num a) =3D> Mlist m a -> m a
productML NIL =3D return 1
productML (x:<:ms) =3D liftM (*x) (ms>>=3D productML)
sequenceML :: Monad m =3D> [m a] -> m(Mlist m a)
sequenceML [] =3D return NIL
sequenceML (x:xs) =3D liftM (:<: sequenceML xs) x
listEmbed :: Monad m =3D> [a] -> Mlist m a
listEmbed [] =3D NIL
listEmbed (x:xs) =3D x :<: return (listEmbed xs)
filterML :: Monad m =3D> (a->Bool) -> Mlist m a -> m(Mlist m a)
filterML _ NIL =3D return NIL
filterML p (x :<: ms)
| p x =3D return (x :<: rs)
| otherwise =3D rs
where rs =3D ms >>=3D filterML p
takeWhileML :: Monad m =3D> (a->Bool) -> Mlist m a -> Mlist m a
takeWhileML _ NIL =3D NIL
takeWhileML p (x :<: ms)
| p x =3D x :<: (liftM (takeWhileML p) ms)
| otherwise =3D NIL =
dropWhileML :: Monad m =3D> (a->Bool) -> Mlist m a -> m(Mlist m a)
dropWhileML _ NIL =3D return NIL
dropWhileML p (x :<: ms)
| p x =3D ms >>=3D dropWhileML p
| otherwise =3D return (x :<: ms)
sequenceWhile_ :: Monad m =3D> (a-> Bool) -> [m a] -> m ()
sequenceWhile_ p xs =3D do
ml<-sequenceML xs
mlToList $ takeWhileML p ml
return ()
showMLIO :: Show a =3D> Mlist IO a -> IO ()
showMLIO NIL =3D putStr "[]"
showMLIO (x:<:ms) =3D =
do
putStr "["
putStr (show x)
ms >>=3D showRest
where
showRest NIL =3D putStr "]"
showRest (y :<: ys) =3D
do
putStr ","
putStr (show y)
ys >>=3D showRest
=
{- not lazy enough -}
showMLx :: (Monad m,Show a) =3D> Mlist m a -> m (String)
showMLx NIL =3D return "[]"
showMLx (x:<:ms) =3D =
liftM (("[" ++ show x) ++) (ms >>=3D showRest)
where
showRest NIL =3D return "]"
showRest (y :<: ys) =3D
liftM ((","++show y)++) (ys >>=3D showRest)
singletonML x =3D x :<: return NIL
showML :: (Monad m,Show a) =3D> Mlist m a -> Mlist m Char
showML NIL =3D listEmbed "[]"
showML (x:<:ms) =3D
'[' :<: (listEmbed(show x) +<+ liftM showRest ms)
where
showRest NIL =3D singletonML ']'
showRest (y:<:ys) =3D
',' :<: (listEmbed(show y) +<+ (liftM showRest ys))
putStrML :: Mlist IO Char -> IO ()
putStrML NIL =3D return ()
putStrML (c :<: cs) =3D putChar c >> (cs >>=3D putStrML)
{-
type StringM m =3D Mlist m Char
type ShowM m =3D m (StringM m) -> m (StringM m)
class ShowML where
showML :: Monad m =3D> a -> m (StringM m)
showsPrecML :: Monad m =3D> Int -> a -> ShowM m
showML t =3D showsPrecML 0 t (return NIL)
showsPrecML n t ms =3D showML t +<+ ms
-}
--==_Exmh_-17196631560--