2016-07-14 13 views
2

Ich bin neu bei Haskell und bin verwirrt darüber, wie man Werte aus Funktionsergebnissen herausholt. In meinem speziellen Fall versuche ich, Haskell-Dateien zu analysieren und zu sehen, welche AST-Knoten in welchen Zeilen angezeigt werden. Dies ist der Code, den ich bisher habe:Informationen aus dem Haskell-Objekt extrahieren

import Language.Haskell.Parser 
import Language.Haskell.Syntax 

getTree :: String -> IO (ParseResult HsModule) 
getTree path = do 
       file <- readFile path 
       let tree = parseModuleWithMode (ParseMode path) file 
       return tree 

main :: IO() 
main = do 
     tree <- getTree "ex.hs" 
     -- <do something with the tree other than print it> 
     print tree 

So auf der Linie, wo ich den Kommentar, ich habe einen Syntaxbaum als tree. Es scheint Typ ParseResult HsModule zu haben. Was ich will, ist nur HsModule. Ich denke, was ich suche eine Funktion ist wie folgt:

extract :: ParseResult a -> a 

Oder noch besser, eine allgemeine Haskell Funktion

extract :: AnyType a -> a 

Vielleicht ein großes Konzept über Haskell ich hier fehlt bin?

p.s. Ich verstehe, dass es falsch ist, über diese Dinge als "Objekte" zu denken und "Felder" von ihnen zu erreichen, aber ich hätte gerne eine Erklärung, wie ich mit dieser Art von Dingen im Allgemeinen umgehen soll.

Antwort

3

Die Definition von ParseResult ist:

data ParseResult a = ParseOk a | ParseFailed SrcLoc String 

(aus dem Quellcode erhalten)

So gibt es zwei Möglichkeiten: Entweder das Parsen erfolgreich war, und es wird eine ParseOk Instanz zurück oder etwas schief gelaufen ist Während des Parsens erhalten Sie in diesem Fall die Position des Fehlers und eine Fehlermeldung mit einem ParseFailed Konstruktor.

So können Sie eine Funktion definieren:

getData :: ParseResult a -> a 
getData (ParseOk x) = x 
getData (ParseFailed _ s) = error s 

Es ist besser, dann auch einen Fehler aus, da es immer möglich ist, dass Ihr Compiler/Interpreter/Analyzer/... ein Haskell Programm analysiert enthält Syntaxfehler.

+2

'getData' ist falsch. Bailing mit 'error' ist der falsche Weg, um einen Parse-Fehler zu behandeln. – dfeuer

1

Ich habe gerade herausgefunden, wie das geht. Es scheint, dass, wenn ich versuche,

extract :: ParseResult a -> a 
extract (ParseResult a) = a 

Ich brauchte eigentlich zu definieren

extract :: ParseResult a -> a 
extract (ParseOk a) = a 

stattdessen zu verwenden. Ich bin mir nicht 100% sicher, warum das so ist.

+1

Vergessen Sie nie, Warnungen zu aktivieren: Sie werden darauf hinweisen, dass Sie vergessen haben, den 'ParseFailed' Fall zu behandeln. Zwei mögliche Ergebnisse zu haben (Erfolg und Misserfolg) ist der ganze Sinn von 'ParseResult'. – chi

+0

Das liegt daran, dass 'ParseResult a' ein Typ ist. Der Mustervergleich akzeptiert nur Muster auf einer Werteebene. Aus diesem Grund müssen Sie Ihren Parameter einem Datenkonstruktor zuordnen. Es ist vergleichbar mit "Vielleicht". Um einen Wert aus einem Wert des Typs "Maybe a" zu extrahieren, müssen Sie ihn mit "Just" vergleichen, nicht mit "Maybe", das wäre nicht sinnvoll. – baxbaxwalanuksiwe

7

die Suche nach einer allgemeinen Funktion vom Typ

extract :: AnyType a -> a 

in der Tat ein großes Missverständnis über Haskell nicht zeigen. Betrachten Sie die vielen Dinge, die AnyType sein könnten, und wie Sie genau ein Objekt daraus extrahieren könnten. Was ist mit Maybe Int? Sie können problemlos Just 5 in 5 konvertieren, aber welche Nummer sollten Sie für Nothing zurückgeben?

Oder was ist, wenn AnyType[] ist, so dass Sie [String] haben?Was sollte das Ergebnis

extract ["help", "i'm", "trapped"] 

oder von

extract [] 

sein?

ParseResult hat ein ähnliches "Problem", in dem es ParseOk verwendet, um Ergebnisse zu enthalten, die anzeigen, dass alles in Ordnung war, und ParseFailed, um einen Fehler anzuzeigen. Ihre unvollständige Musterübereinstimmung erhält das Ergebnis, wenn die Syntaxanalyse erfolgreich war, stürzt jedoch Ihr Programm ab, wenn die Analyse tatsächlich fehlgeschlagen ist. Mithilfe von ParseResult ermutigt Haskell Sie dazu, zu überlegen, was Sie tun sollten, wenn der Code, den Sie analysieren, nicht korrekt analysiert wurde, anstatt einfach mit der Annahme, dass es gut ausgehen wird.

+0

Das macht Sinn. Was ich nicht verstand, ist, dass 'ParseResult' 2 und nur 2 mögliche Werte hat:' ParseOk' und 'ParseFailed', die um den eigentlichen Wert gewickelt sind (' HsModule' im Erfolgsfall und 'SrcLoc' &' String') im Fehlerfall). – nullromo

Verwandte Themen