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 =
do xs <- getStrings
putStrLn(headML xs)
getStrings =
do { x <- getLine; if x=="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
module ListForMonad where
import Monad
data Mlist m a = NIL | a :<: m (Mlist m a)
nullML :: Mlist m a -> Bool
nullML NIL = True
nullML _ = False
(<:) :: Monad m => a -> m (Mlist m a) -> m (Mlist m a)
x <: ms = return (x :<: ms)
(+<+) :: Monad m => Mlist m a -> m (Mlist m a) -> m (Mlist m a)
xs +<+ ms = foldrML (<:) ms xs
(!<!) :: Monad m => Mlist m a -> Int -> m a
NIL !<! _ = error "index out of bounds"
(x :<: ms) !<! 0 = return x
(_ :<: ms) !<! n = ms >>= (!<! (n-1))
lengthML :: Monad m => Mlist m a -> m Int
lengthML NIL = return 0
lengthML (_ :<: ms) = liftM (+1) (ms >>= lengthML)
headML :: Mlist m a -> a
headML (x :<: _ ) = x
headML NIL = error "head of empty list"
lastML :: Monad m => Mlist m a -> m a
lastML (x :<: ms) =
do xs<-ms
case xs of NIL -> return x
p -> lastML p
lastML NIL = error "last of empty list"
tailML :: Mlist m a -> m (Mlist m a)
tailML (_ :<: ms) = ms
tailML NIL = error "tail of empty list"
initML :: Monad m => Mlist m a -> m (Mlist m a)
initML NIL = error "init of empty list"
initML (x :<: ms) =
do xs<-ms
case xs of NIL -> return NIL
p -> return (x :<: initML p)
replicateML :: Monad m => Int -> m a -> m (Mlist m a)
replicateML n a = liftM (takeML n) (repeatML a)
repeatML :: Monad m => m a -> m (Mlist m a)
repeatML action = xs
where
xs = do { r<-action; return (r :<: xs) }
takeML :: Monad m => Int -> Mlist m a -> Mlist m a
takeML _ NIL = NIL
takeML 0 _ = NIL
takeML n (x:<:ms) = x :<: (liftM (takeML (n-1)) ms)
dropML :: Monad m => Int -> Mlist m a -> m(Mlist m a)
dropML 0 xs = return xs
dropML _ NIL = return NIL
dropML n (x:<:ms) = ms >>= dropML (n-1)
splitAtML :: Monad m => Int -> Mlist m a -> m (Mlist m a, m(Mlist m a))
splitAtML 0 xs = return (NIL, return xs)
splitAtML n NIL = return (NIL, return NIL)
splitAtML n (x:<: ms) =
do m<-ms
(as,ns)<-splitAtML (n-1) m
return (x :<: return as,ns)
reverseML :: Monad m => Mlist m a -> m (Mlist m a)
reverseML ms =
do xs <- mlToList ms
foldr (<:) (return NIL) (reverse xs)
zipML :: Monad m => Mlist m a -> Mlist m b -> Mlist m (a,b)
zipML (x:<:ms) (y:<:ns) = (x,y) :<: do { xs<-ms; ys<-ns; return(zipML xs ys) }
zipML _ _ = NIL
unzipML :: Monad m => Mlist m (a,b) -> (Mlist m a,Mlist m b)
unzipML xs = (fmap fst xs,fmap snd xs) {- note: re-evaluation -}
instance Monad m => Functor (Mlist m) where
fmap f NIL = NIL
fmap f (x:<:ms) = f x :<: (liftM (fmap f) ms)
mlToList :: Monad m => Mlist m a -> m [a]
mlToList NIL = return []
mlToList (x :<: ms) = liftM (x:)(ms >>= mlToList)
foldrML :: Monad m => (a -> m b -> m b) -> m b -> Mlist m a -> m b
foldrML f n NIL = n
foldrML f n (x :<: ms) = f x (ms >>= foldrML f n)
blift :: Monad m => (a->b->b) -> (a-> m b -> m b)
blift f x act = liftM (f x) act
(&<&) :: Monad m => Bool -> m Bool -> m Bool
True &<& xs = xs
False &<& _ = return False
(|<|) :: Monad m => Bool -> m Bool -> m Bool
True |<| xs = return True
False |<| xs = xs
andML :: Monad m => Mlist m Bool -> m Bool
andML xs = foldrML (&<&) (return True) xs
orML :: Monad m => Mlist m Bool -> m Bool
orML xs = foldrML (|<|) (return False) xs
anyML :: Monad m => (a->Bool) -> Mlist m a -> m(Bool)
anyML p xs = orML $ fmap p xs
allML :: Monad m => (a->Bool) -> Mlist m a -> m(Bool)
allML p xs = andML $ fmap p xs
sumML :: (Monad m,Num a) => Mlist m a -> m a
sumML NIL = return 0
sumML (x:<:ms) = liftM (+x) (ms>>= sumML)
productML :: (Monad m,Num a) => Mlist m a -> m a
productML NIL = return 1
productML (x:<:ms) = liftM (*x) (ms>>= productML)
sequenceML :: Monad m => [m a] -> m(Mlist m a)
sequenceML [] = return NIL
sequenceML (x:xs) = liftM (:<: sequenceML xs) x
listEmbed :: Monad m => [a] -> Mlist m a
listEmbed [] = NIL
listEmbed (x:xs) = x :<: return (listEmbed xs)
filterML :: Monad m => (a->Bool) -> Mlist m a -> m(Mlist m a)
filterML _ NIL = return NIL
filterML p (x :<: ms)
| p x = return (x :<: rs)
| otherwise = rs
where rs = ms >>= filterML p
takeWhileML :: Monad m => (a->Bool) -> Mlist m a -> Mlist m a
takeWhileML _ NIL = NIL
takeWhileML p (x :<: ms)
| p x = x :<: (liftM (takeWhileML p) ms)
| otherwise = NIL
dropWhileML :: Monad m => (a->Bool) -> Mlist m a -> m(Mlist m a)
dropWhileML _ NIL = return NIL
dropWhileML p (x :<: ms)
| p x = ms >>= dropWhileML p
| otherwise = return (x :<: ms)
sequenceWhile_ :: Monad m => (a-> Bool) -> [m a] -> m ()
sequenceWhile_ p xs = do
ml<-sequenceML xs
mlToList $ takeWhileML p ml
return ()
showMLIO :: Show a => Mlist IO a -> IO ()
showMLIO NIL = putStr "[]"
showMLIO (x:<:ms) =
do
putStr "["
putStr (show x)
ms >>= showRest
where
showRest NIL = putStr "]"
showRest (y :<: ys) =
do
putStr ","
putStr (show y)
ys >>= showRest
{- not lazy enough -}
showMLx :: (Monad m,Show a) => Mlist m a -> m (String)
showMLx NIL = return "[]"
showMLx (x:<:ms) =
liftM (("[" ++ show x) ++) (ms >>= showRest)
where
showRest NIL = return "]"
showRest (y :<: ys) =
liftM ((","++show y)++) (ys >>= showRest)
singletonML x = x :<: return NIL
showML :: (Monad m,Show a) => Mlist m a -> Mlist m Char
showML NIL = listEmbed "[]"
showML (x:<:ms) =
'[' :<: (listEmbed(show x) +<+ liftM showRest ms)
where
showRest NIL = singletonML ']'
showRest (y:<:ys) =
',' :<: (listEmbed(show y) +<+ (liftM showRest ys))
putStrML :: Mlist IO Char -> IO ()
putStrML NIL = return ()
putStrML (c :<: cs) = putChar c >> (cs >>= putStrML)
{-
type StringM m = Mlist m Char
type ShowM m = m (StringM m) -> m (StringM m)
class ShowML where
showML :: Monad m => a -> m (StringM m)
showsPrecML :: Monad m => Int -> a -> ShowM m
showML t = showsPrecML 0 t (return NIL)
showsPrecML n t ms = showML t +<+ ms
-}