2016-04-16 8 views
0

Noch einmal bin ich mit Haskell festgefahren. Diesmal sollte ich einen CSV-Datensatz filtern, mit IO, den ich nicht verstehen kann. Alle weiteren damit verbundenen Informationen sind willkommen.Haskell I/O: Leere Listen im CSV-Datensatz filtern

Die Struktur ist vorbestimmt, und mir scheint es chaotisch. Soll das wirklich so sein? (Ich muss es immer noch so machen, also ist das ein wenig "auf der Seite" -Frage).

getRawData' :: String -> IO [[String]] 
getRawData' fn = do 
    s <- readFile fn 
    return $ parseCSVsimple s 



getRawData :: String -> IO [[String]] 
getRawData fn = do 
    d <- getRawData' fn 
    return (dropEmpty d) 



dropEmpty [[String]] -> [[String]] 

DropEmpty - Dies ist, wo ich Für einen „normalen“ -Liste die Hilfe benötigen, würde ich es nur einfach filtern, aber das IO und sich gegenseitig anrufen verschiedene Funktionen hat mich verwirrt.

Sorry für dumme Fragen, ich habe für 8 Monate programmiert und musste seitdem 6-7 Sprachen verwenden. Alle allgemeinen Informationen zu der Frage werden ebenfalls sehr geschätzt.

BEARBEITEN; Follow-up:

Dank der guten Antworten, die ich habe mein Verständnis verbessert und implementiert den folgenden Code:

dropEmpty :: [[String]] -> [[String]] 
dropEmpty = filter(not . null) 

Allerdings habe ich noch leere Listen in der Liste zu sehen. Ist das, weil ich überprüfe, ob die ganze Liste von Listen leer ist? Wie stelle ich fest, dass ich die "internen" Listen überprüfen möchte?

+2

Sobald Sie 'dropEmpty' erreicht haben, sind Sie außerhalb von IO und müssen sich nur noch mit reinem Haskell beschäftigen. Filtern Sie es einfach wie eine normale Liste. – MicroVirus

+0

Ihre DropEmpty-Funktion ist korrekt. Denken Sie daran, dass die Liste von Haskell unveränderlich ist, damit Ihre DropEmpty-Eingabeliste nicht geändert wird. Sie müssen das Ergebnis der Funktion überprüfen. – Bruno

Antwort

1

Das tun Schlüsselwort ist nur eine Zucker Syntax für Monaden

Monad sind wie folgt definiert:

class Monad m where 
    (>>=) :: m a -> (a -> m b) -> m b 
    return :: a -> m a 

Ihre getRawData Funktion entspricht

getRawData fn = getRawData' fn >>= \d -> return (dropEmpty d) 

Wie Sie in der sehen Monad Definition, das zweite Argument von >>= ist der innere Typ der Monade, in Ihrem Fall ist es [[String]]

Also nichts falsch mit Ihrem Code ist, können Sie Ihre dropEmpty ohne sich Gedanken über IO verwenden

+0

Vielen Dank! Ich werde es jetzt herausfinden können – NorwegianViking

1
getRawData :: String -> IO [[String]] 
getRawData fn = do 
    d <- getRawData' fn 
    return (dropEmpty d) 

getRawData und return die monadische Aktionen in diesem tun Block sind. Alle anderen Ausdrücke haben nicht den Typ IO.

Insbesondere der Ausdruck auf der linken Seite von <-, nämlich d, hat gerade die Ebene Typ [[String]]. Alle Parameter, nämlich fn :: String und (dropEmpty d) :: [[String]], sind ebenfalls nicht in IO.

So können Sie leicht nicht-monadischen Werte (z. B. d) aus den monadischen Aktionen (z. B. getRawData') leicht erhalten. Sie können dies jedoch nur vorübergehend tun: Sie können d nicht in den do Block umwandeln, nur IO d. Dies ist ein "Kernmerkmal" von Monaden im Allgemeinen.

Dies ist nur eine sehr oberflächliche Erklärung, um Ihnen einen schnellen Einstieg in den monadischen Code zu geben. Ich empfehle Ihnen, sich über Monaden zu informieren. Erfahren Sie, wie Monaden entzuckert werden. Nehmen Sie zum Beispiel die state Monade, und verstehen Sie, welches Problem es löst, indem Sie versuchen, es erneut zu implementieren.

+0

Vielen Dank :) Ich denke, dass ich in der Lage sein wird, daraus einen Sinn zu machen! – NorwegianViking