Ich möchte eine Liste der Strings lesen, die durch Zeilenumbrüche von STDIN getrennt sind, bis eine neue Zeile zu sehen ist und ich eine Aktion vom Typ IO [String]
möchte. Hier ist, wie ich es mit Rekursion tun würde:Der Haskell-Weg, IO-Loops (ohne explizite Rekursion) zu machen?
myReadList :: IO String
myReadList = go []
where
go :: [String] -> IO [String]
go l = do {
inp <- getLine;
if (inp == "") then
return l;
else go (inp:l);
}
Dieses Verfahren ist jedoch von unterwegs mit verschleierter Lesbarkeit und ist ein Muster, so verbreitet, dass man idealerweise zu abstrahieren diesen wollen würde.
So, das war mein Versuch:
whileM :: (Monad m) => (a -> Bool) -> [m a] -> m [a]
whileM p [] = return []
whileM p (x:xs) = do
s <- x
if p s
then do
l <- whileM p xs
return (s:l)
else
return []
myReadList :: IO [String]
myReadList = whileM (/= "") (repeat getLine)
ich dort bin zu raten, ist einige Standardimplementierung dieser whileM
oder etwas ähnliches bereits. Aber ich kann es nicht finden.
Könnte jemand darauf hinweisen, was der natürlichste und eleganteste Weg ist, um mit diesem Problem umzugehen?
whileM ist in Control.Monad.Loops. –
@ n.m. Ich weiß, aber es macht etwas anderes. Es hat auch eine andere Signatur: 'Monad m => m Bool -> ma -> m [a]' –
Ihre Version scheint nahe zu entfalten, aber Sie nehmen eine Liste von monadischen Aktionen, die Sie nicht wirklich brauche (du generierst die Liste trotzdem mit repeat). –