www.jammni.de

Logo - Kleiner Drache
Login
Username:

Passwort:

Daten merken
Auto-Login
Registrieren
 
Online
niemand
 
Forumsuche
Suche nach:

Logo - DracheHaskell-Forum

  1 2 nächste Seite

HaskellAnfänger2

Gepostet:
05.02.2011 16:26

Zufallsfunktion soll zufällige Zahl liefern - Hilfe  
Ich habe schon überall geguckt, habe aber keine Funktion gefunden, die ohne eingabe von parametern mir eine zufällige Zahl liefert.

Diese Funktion habe ich schon getestet, aber als ergebniss bekomm ich nur eine leertaste:

  rollDice :: IO Int
rollDice = getStdRandom (randomR (1,6))

Und diese hier auch schon:

main = do
gen <- newStdGen
let ns = randoms gen :: [Int]
print $ take 1 ns

Hier habe ich das Problem, dass ich eine zufällige zahl bekomme, jedoch nicht in einem bereich von z.B. 1-40.

Mach ich etwas falsch?
Könnt ihr mir eventuell helfen und eine Funktion sagen, mit der ich ohne Eingabe von Parametern eine zufällige Zahl in einem bestimmten Bereich bekomme.

Vielen Dank im Voraus,

HaskellAnfänger2
Zum Seitenanfang    
 
Siracusa

Gepostet:
05.02.2011 17:34

   
Hallo,

dein erstes Beispiel ist korrekt. Was meinst du da mit "Leertaste"? Das Ergebnis ist eine I/O-Aktion, die eine Zahl zwischen 1 und 6 liefert. Alternativ kannst du auch randomRIO (1,6) verwenden, was praktisch das gleiche Ergebnis liefert.


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
HaskellAnfänger2

Gepostet:
06.02.2011 17:46

   
Was genau bedeutet I/O-Aktion? Ich bin echt blutiger Anfänger bei Haskell. Also wir haben das in der Schule gemacht.

Mein Problem ist wenn ich bei Haskell dann rollDice eingebe, kommt irgendwie keine Zahl raus. Ich seh halt nicht was das ergebnis ist. Ich hoffe du verstehst mein Problem. Oder kommt da ein ergebnis raus nur sehe ich keine Zahl?

So Sieht das bei mir aus: http://www.pictureupload.de/originals/pictures/060211174926_Haskell.JPG

Vielen Danke im Voraus,

HaskellAnfänger
Zum Seitenanfang    
 
Siracusa

Gepostet:
06.02.2011 18:40

   
Ok, da muss ich etwas ausholen :-)

Bei Haskell musst du zwischen Funktionen ohne Seiteneffekte (engl.: pure functions) und sog. monadischen Funktionen unterscheiden. Zu den ersteren gehören bspw. Funktionen vom Typ Int -> Int, String -> [String], usw., also alle Funktionen, die bei gleichen Parametern immer das gleiche Ergebnis liefern und keinen globalen Zustand verändern. Zu den monadischen Funktionen gehören alle die, die potentiell bei gleichen Eingaben unterschiedliche Ausgaben liefern können. Zudem sind Seiteneffekte erlaubt und die Auswertungsreihenfolge der Ausdrücke kann vorgegeben sein.

Da deine Zufallsfunktion immer unterschiedliche Werte liefern soll, kann sie nicht "pure" sein. Es gibt also zwei Möglichkeiten: Du verwendest eine Funktion die als Parameter einen Zufallszahlengenerator erwartet und daraus eine neue Zufallszahl generiert + den neuen Zufallsgenerator zurückgibt (random, randomR); oder du verwendest eine monadische Funktion - in dem Fall in der IO-Monade - und lässt dir innerhalb der Monade unter Verwendung eines globalen Zufallsgenerators Zufallswerte zurückgeben (randomIO, randomRIO). Die IO-Monade erlaubt bspw. auch das Einlesen von Tastendrücken, die Ausgabe von Text auf der Konsole oder auch Dateizugriffe.

Die Crux der IO-Monade ist allerdings, wenn du einmal einen I/O-Wert verwendest kommst du nicht mehr aus der IO-Monade heraus. Heißt also, wenn du eine Funktion verwendest, die einen Wert vom Typ IO Int liefert, muss dein gesamtes Funktionsergebnis auch vom Typ IO irgendwas sein. Das ist in der Regel aber kein Problem, da ein Haskell-Programm (= die main-Funktion) ohnehin vom Typ IO () ist.

Lange Rede, kurzer Sinn: rollDice macht genau was es soll, das Problem liegt nur bei der Ausgabe des Ergebnisses. Du benutzt offenbar Hugs oder WinHugs, wo I/O-Aktionen scheinbar nicht automatisch im Interpreter ausgewertet werden (der GHCi macht das nämlich). Willst du die Funktion also einmal "würfeln lassen", kannst du folgende Funktion verwenden:
roll :: IO ()
roll = do
i <- rollDice
print i

-- oder kürzer:

roll = rollDice >>= print

Die erste Version führt rollDice aus und bindet das Ergbenis an die Variable i. Daraufhin wird i auf der Konsole ausgegeben. Die verwendete Schreibweise nennt man do-Notation, die es erlaubt das Programm in einem imperativen Stil zu schreiben.

Das Thema Monaden ist ein weites Feld, du solltest dir aber wenigstens eine Einführung zur IO-Monade (z.B. diese hier http://www.haskell.org/haskellwiki/Introduction_to_IO) durchlesen.


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
HaskellAnfänger2

Gepostet:
07.02.2011 21:01

   
Vielen vielen Dank das ist echt super. Vor allem habe ich es nun einigermaßen verstanden. Mein Problem ist jetzt nur noch, dass ich sowas in meinem Hugs rausbekomme:

Kurze erklärung, ich will eine Funtktion antwort haben, die eine zufällige Zahl mit einer Liste vergleicht und mir ein ergebnis liefert. So sieht das momentan bei mir aus:


rollDice :: IO Int
rollDice = getStdRandom (randomR (1,6))

roll = rollDice >>= print

antwort = vergleichen (roll)

vergleichen c = vergleichenhelp c hilfsliste

vergleichenhelp c [] = c
vergleichenhelp c ((a,b):xs)
|c == a = b
|otherwise = vergleichenhelp c (xs)

hilfsliste = [("1","Weiter"),("2","Danke")]

Nun bekomme ich aber im Hugs folgende Fehlermeldung:

ERROR file:.\io Eliza(1).hs:46 - Type error in application
*** Expression : vergleichen roll
*** Term : roll
*** Type : IO ()
*** Does not match : [Char]


Kannst du mir nocheinmal weiterhelfen? Das wäre super, dann hätte ich alles was ich brauche.

Vielen Dank nochmal das du dich überhaupt mit so einem, wahrscheinlich Anfängerproblem, beschäftigst. Daaanke!

Viele Grüße,

HaskellAnfänger
Zum Seitenanfang    
 
Landei

Gepostet:
08.02.2011 16:13

   
Ich hoffe, das ich das richtig verstanden habe: Mit dem Ergebnis aus rollDice soll ein Eintrag aus hilfsliste herausgesucht und ausgegeben werden.

Zuerst zu hilfsliste: Das erste Element der Paare ein Int sein, denn rollDice liefert ein Int und keinen String:


hilfsliste = [(1,"Weiter"),(2,"Danke")]


Nun gibt es für das Finden von Einträgen in solchen Listen schon eine fertige Funktion, nämlich lookup: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:lookup (Hoogle ist dein Freund)

Der Rückgabewert von lookup ist ein Maybe, weil man ja nicht garantieren kann, dass tatsächlich etwas gefunden wird (und ein Error etwas hart wäre). In deinem Fall werden natürlich "Würfe" größer zwei nicht gefunden und liefern dann Nothing. Natürlich ist es pädagogisch wertvoll, wenn du versuchst, deine eigene Version oder Variante davon zu schreiben.

Die roll-Funktion schreibt sich am bequemsten in do-Notation:


roll = do
value <- rollDice
print $ lookup value hilfsliste


Wenn es unbedingt die bind-Notation sein soll, ginge es z.B. so:


roll = rollDice >>= (\value -> print $ lookup value hilfsliste)


roll gibt in zufälliger Folge Just "Weiter", Just "Danke" oder Nothing aus.
Zum Seitenanfang    
 
HaskellAnfänger2

Gepostet:
08.02.2011 22:59

   
Das hört sich super an. Ich bin immernoch begeistert von der schnellen Hilfe, ihr seit super!

Nun habe ich nur noch ein Problem, und zwar, dass als Fehlermeldung sowas kommt:

ERROR file:.\io Eliza(1).hs:44 - Type error in application
*** Expression : lookup value hilfsliste
*** Term : value
*** Type : Int
*** Does not match : Integer

Wenn ihr mir hier auch noch weiterhelfen könntet wäre ich fertig und gleichzeitig unendlich dankbar :)

Viele Grüße,

HaskellAnfänger
Zum Seitenanfang    
 
Siracusa

Gepostet:
08.02.2011 23:52

   
Füge mal zu allen Funktionen Typsignaturen hinzu, also bspw. hilfsliste :: [(Int, String)]. Wenn du diese weglässt bestimmt der Compiler zwar selbst einen Typ, alle Zahlen werden standardmäßig aber zu Integer spezialisiert. Wenn dann an andere Stelle ein Int gefordert ist gibt es den Typfehler. Außerdem helfen explizite Typsignaturen Fehler schneller zu finden und das Schreiben der Funktionen klappt oft auch viel besser, wenn man sich darüber im Klaren ist, welchen Typ die Funktion zum Schluss haben soll.


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
HaskellAnfänger2

Gepostet:
09.02.2011 16:10

   
Ok nun habe ich wieder ein anderes Problem. Und ich verstehe diese Fehlermeldungen irgendwie überhauptnicht. Könnt ihr mir bitte nochmal helfen?

ERROR file:.\io Eliza(richtig).hs:19 - Type error in application
*** Expression : elizahelp (words (großschreiben str)) elizadatenbank
*** Term : elizadatenbank
*** Type : [([Char],[Char])]
*** Does not match : [(a,IO ())]


Hierbei ist elizadatenbank eine Liste und elizahelp eine Funktion, die den eingegebenen String mit der liste vergleicht. So grob gesagt, aber es ist natürlich ein bisschen komplizierter.

Vielen Danke im Voraus,

HaskellAnfänger
Zum Seitenanfang    
 
Landei

Gepostet:
09.02.2011 16:16

   
Ohne Code können wir nur rumraten:

Hast du mal bei elizahelp den Typ angegeben? Funktioniert die Funktion elizahelp für sich alleine? Ist der Typ [([Char],[Char])] a.k.a. [(String,String)] für elizadatenbank korrekt?

Zum Seitenanfang    
 

  1 2 nächste Seite