Benutzer:Dirk Huenniger/haskell
Hier stelle ich kurz ein Möglichkeit vor die Lazy Evaluation Eigenschaft von Haskell im Rahmen von IO zu verwenden. Ich lade drei Webseiten simultan herunter und gebe Summe der Lägen der Seiten in Bytes aus. Offenbar müssen alle drei Seiten vollständig herunter geladen worden sein ehe die Summe berechnet werden kann. Hierzu werden üblicherweise Synchronisationsverfahren, wie Semaphore, Locks, Futures etc. verwendet. In diesem Beispiel konnte auf die Explizite Verwendung derartiger Strukturen verzichtet werden. Es ist jedoch stark zu erwarten das Compiler und Laufzeitumgebung sie in geeigneter Weise nutzen. Es ist jedoch sehr angenehm diese Arbeiten an die Programmiersprache abgeben zu können und sie nicht mehr explizit definieren zu müssen. Als erstes zeige ich einen Java artigen Pseudocode. Anschließend eine lauffähiges Haskell Programm und schließlich ein lauffähiges Java Programm.
PseudoCode
Char [] a
Char [] b
Char [] c
a= performThreaded ( getUrl("http://www.python.org") )
b= performThreaded ( getUrl("http://www.haskell.org") )
c= performThreaded ( getUrl("http://www.google.de") )
System.out.println(a.length+b.length+c.length )
Ausgabe:
Getting URL http://www.python.org
Getting URL http://www.haskell.org
Getting URL http://www.google.de
Got URL http://www.python.org
Got URL http://www.google.de
Got URL http://www.haskell.org
49690
Haskell
import Network.HTTP
import Network.HTTP.Headers
import Network.HTTP.Base
import Network.TCP
import Network.Browser
import Network.URI
import Control.Concurrent
import Char
import System.IO.Unsafe
evoke :: (IO a)-> (IO a)
evoke x= do
y<-newEmptyMVar
forkIO $ (\ yy-> do {r<-x; putMVar yy r }) y
yy<-unsafeInterleaveIO (takeMVar y)
return yy
main = do
x<- evoke (getURL "http://www.python.org")
y<- evoke (getURL "http://www.haskell.org")
z<- evoke (getURL "http://www.google.de")
print (( length x)+( length y)+( length z))
getURL :: String -> IO String
getURL x=do
putStrLn ("Getting URL "++x)
y<-simpleHTTP (getRequest x)
let z = getBody y
putStrLn ("Got URL "++x)
return z
getBody (Right x)= rspBody x
getRequest x = (getRequestHelper (parseURI x))
getRequestHelper (Just x)= (defaultGETRequest x ){ rqHeaders= [Header HdrCacheControl "max-age=0", Header HdrUserAgent "Secret Organisation for Contemporary Concurrent Monadic Terrorism"]}
Java
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
interface URLGetter {
List<Integer> get(List<URL> in);
}
class URLGetHelper {
static Integer get(URL x) {
try {
InputStreamReader s=new InputStreamReader(x.openStream());
int got=0;
while (true) {
if (s.read()<0) {
return got;
}
else {
got++;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
class SimpleURLGetter implements URLGetter {
public List<Integer> get(List<URL> in) {
LinkedList<Integer> out=new LinkedList<Integer>();
for (URL x : in) {
out.add(URLGetHelper.get(x));
}
return out;
} }
class URLTask extends FutureTask<Integer> {
public URLTask(final URL x) {
super(new Callable<Integer>() {
public Integer call() throws Exception {
return URLGetHelper.get(x);
}});
}
}
class ThreadedURLGetter implements URLGetter {
public List<Integer> get(List<URL> in) {
LinkedList<Integer> out=new LinkedList<Integer>();
LinkedList <URLTask> tasks=new LinkedList<URLTask>();
for (URL x : in) {
URLTask t=new URLTask(x);
new Thread(t).start();
tasks.add(t);
}
for (URLTask t : tasks) {
try {
out.add(t.get());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return out;
} }
public class Loader {
public static void main(String [] argv) throws MalformedURLException {
LinkedList<URL> l=new LinkedList<URL>();
l.add(new URL("http://python.org"));
l.add(new URL("http://en.wikipedia.org"));
l.add(new URL("http://haskell.org"));
l.add(new URL("http://www.java.com"));
Date d2=new Date();
System.out.println((new ThreadedURLGetter()).get(l));
System.out.println((new Date()).getTime()-d2.getTime());
Date d1=new Date();
System.out.println((new SimpleURLGetter()).get(l));
System.out.println((new Date()).getTime()-d1.getTime());
}
}