www.jammni.de

Logo - Kleiner Drache
Login
Username:

Passwort:

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

Logo - DracheHaskell-Forum

Kotori

Gepostet:
22.11.2009 12:17

Testen auf 3 Prädikate  
Hallo!

Ich soll eine Funktion schreiben, die eine Liste in vier Teillisten filtert (die vierte ist die, auf die nichts zutrifft!), anhand von Bedingungen.
Das Problem dabei ist, dass ich offenbar nur einen Filter dazu verwenden darf :(

Meine Frage wäre jetzt, ob es eine Möglichkeit gibt 3 Filter quasi in einen umzuformen. Ich habe bereits probiert mit 3 Filtern zu arbeiten, aber dann stimmt ja die Signatur sieb :: [a -> Bool] -> [a] -> [[a]] nicht länger.

die Beschreibung sagt folgendes:
* Die Werte aus einer Liste werden mit Prädikaten aus einer weiteren Liste geprüft.
* Die Prädikate (Funktionen mit einem Parameter und einem boolschen Rückgabewert) werden nacheinander angewandt.
* Liefert ein Prädikat True, so wird der Wert in die entsprechende Ergebnisliste eingefügt. Andernfalls wird mit dem nächsten Prädikat geprüft.
* Werte, für die kein Prädikat erfüllt ist, kommen in eine eigene Liste als letztes Element der Ergebnisliste.

Ein Beispiel für so eine Funktion wäre das hier:

sieb [(<3),(>7),odd] [1..10] liefert [[1,2],[8,9,10],[3,5,7],[4,6]]

Muss ich dann doch mit 3 Filtern arbeiten? Wie kommt es dann, dass nur einmal a -> Bool in der signatur steht?

Bin dankbar für jeden Tipp! ;)

Zum Seitenanfang    
 
Siracusa

Gepostet:
22.11.2009 17:05

   
Hi,

Wie kommt es dann, dass nur einmal a -> Bool in der signatur steht?

Dort steht ja [a -> Bool] mit eckigen Klammern, also ist es eine Liste von Prädikaten. Bei runden Klammern wäre es nur eins. Wieviel genau zur Laufzeit dann wirklich drinstehen kann man vorher nicht wissen (es könnte theoretisch auch eine leere Liste sein).

Wenn es bei dir aber immer genau drei Prädikate sind, vereinfacht sich die Sache schon etwas. Dann könntest du eine Hilfsfunktion sieb' nach folgendem Prinzip aufbauen:

sieb' [p1, p2, p3] []     xs1 xs2 xs3 xsRest = Liste mit xs1 bis xsRest
sieb' [p1, p2, p3] (x:xs) xs1 xs2 xs3 xsRest
| Prädikat p1 passt = sieb' [p1, p2, p3] xs (x:xs1) xs2 xs3 xsRest
| ...
| kein Prädikat passt = sieb' [p1, p2, p3] xs xs1 xs2 xs3 (x:xsRest)

xs1 bis xsRest sind hier Hilfsparameter, die jeweils dem aktuellen Stand der Ergebnislisten entsprechen. Wenn ein Prädikat passt, wird der Wert x an die jeweilige Hilfsliste angehängt, wenn nichts passt kommt der Wert auf die Restliste xsRest. Zum Schluss werden alle Hilfslisten in eine einzelne Liste gepackt und als Ergebnis zurückgegeben. Aufgerufen wird sieb' natürlich mit [] für alle Hilfslisten.

Wenn das ganze auch für beliebig viele Prädikate funktionieren soll, wird es natürlich komplizierter. Dann müssten die Prädikatenliste und eine Hilfslistenliste immer parallel abgearbeitet werden.


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
Luks

Gepostet:
23.11.2009 10:29

   
also ich habs mal versucht, aber es schient nicht zu funktionieren


sieb :: [a -> Bool] -> [a] -> [[a]]
sieb [p1,p2,p3] xs = sieb' xs


sieb' [p1,p2,p3] [] [xs1,xs2,xs3,xsRest] = [xs1,xs2,xs3,xsRest]
sieb' [p1,p2,p3] (x:xs) [xs1,xs2,xs3,xsRest]
| p1 x == True = sieb' [p1,p2,p3] xs [(x:xs1), xs2, xs3, xsRest]
| p2 x == True = sieb' [p1,p2,p3] xs [xs1, (x:xs2), xs3, xsRest]
| p3 x == True = sieb' [p1,p2,p3] xs [xs1, xs2, (x:xs3), xsRest]
|otherwise = sieb' [p1,p2,p3] xs [xs1, xs2, xs3, (x:xsRest)]


kommt die fehlermeldung:
Type error in explicitly typed binding
*** Term : sieb
*** Type : [(a -> Bool) -> Bool] -> [a -> Bool] -> [a] -> [[a]] -> [[a]]
*** Does not match : [(a -> Bool) -> Bool] -> [a -> Bool] -> [[a -> Bool]]

Zum Seitenanfang    
 
Siracusa

Gepostet:
23.11.2009 15:55

   
Hallo,

dein Aufruf von sieb' ist falsch. Du übergibst weder die Prädikatenliste, noch initialisierst du die Hilfslisten.


Viele Grüße,

Siracusa
Zum Seitenanfang