2016-05-04 8 views
0

So habe ich in den letzten paar Tagen mit Haskell gespielt, und ich entschied, dass ich eine grundlegende Definition der Fibonacci-Sequenz machen würde. Also schrieb ich diesen Code:Haskell sagt, meine Wache hat einen Parse Error

main = do 
    fib :: (Integral a) => Int -> Int 
    fib x 
     | x == 0 = 0 
     | x == 1 = 1 
     | x >= 2 = fib (x - 2) + fib (x - 1) 
    do { print (fib 5) } 

Und ich erhalte eine Fehlermeldung, die besagt:

4:17: parse error on input `|' 

I Tab Fehler vermutet wird, so habe ich versucht, alle Leerzeichen fix ich finden konnte, aber ich kann einfach nicht finden Was ist los mit dir!

EDIT: Also tat ich, was die Leute vorgeschlagen, und ich habe diesen Code jetzt:

fib :: (Integral a) => Int -> Int 
main = do 
    fib x 
     | x == 0 = 0 
     | x == 1 = 1 
     | x >= 2 = fib (x - 2) + fib (x - 1) 
    print (fib 5) 

und ich bin der gleiche Fehler.

+0

Beliebig Warum setzen Sie Typ-Signatur und Funktionsdefinition in den Do-Block? – jakubdaniel

+0

Ich wusste nicht, was ich tat. – ThePhillipParadox

Antwort

1

Sie können auch fib lokal zu main außerhalb des do Blocks definieren. Denken Sie daran, dass do syntaktischer Zucker für die Verwendung von verschiedenen monadischen Bindungsfunktionen ist, und daher ist die Syntax, die darin akzeptiert wird, nicht ganz die gleiche wie die, die außerhalb davon akzeptiert wird. Und in der Tat, Ihre main erfordert nicht einmal die do Block, weil Sie einfach print aufrufen, anstatt alle Aktionen zusammen IO verketten.

main = let 
     fib x | x == 0 = 0 
       | x == 1 = 1 
       | x >= 2 = fib (x - 2) + fib (x + 1) 
     in 
     print (fib 5) 

Oder Sie könnten where verwenden:

main = print (fib 5) 
     where 
     fib x | x == 0 = 0 
       | x == 1 = 1 
       | x >= 2 = fib (x - 2) + fib (x + 1) 

sind sie gleich, die Frage nur, wo die lokale Bindung tatsächlich geht. let .. in gibt Ihnen einen neuen Block, in dem sich die neuen Bindungen befinden, während where seine Bindungen im Rahmen der Funktion bereitstellt, an die sie angehängt ist.

Wenn, wie schließlich wahrscheinlich scheint, Sie auch einen do Block wollen, so dass Sie mehrere IO Aktionen ausführen können, können Sie nur das zu print des Anrufs in Kraft gesetzt, etwa so:

main = let 
     fib x | x == 0 = 0 
       | x == 1 = 1 
       | x >= 2 = fib (x - 2) + fib (x + 1) 
     in 
     do print (fib 5) 
      print (fib 6) 
3

Sie sollten außerhalb von main definieren, nicht darin. Und dann sollten Sie mindestens einen der do s aus main entfernen.

+1

die 'Do's sind kein Problem Ich würde sagen, Sie können sie verschachteln. Wenn Sie jedoch eine Variable innerhalb eines Do-Blocks binden wollen, müssen Sie 'let' verwenden. – jakubdaniel

+0

Sicher, aber sie sind immer noch schlecht und komisch. – amalloy

+0

Ich habe "fib :: (Integral a) => Int -> Int" nach "main" verschoben, aber ich bekomme den gleichen Fehler. – ThePhillipParadox

3

Das Problem ist, dass Sie versuchen, die Funktion innerhalb do Block zu definieren, ohne tatsächlich ein Konstrukt für die Definition von Dingen zu verwenden (wie let).

Versuchen Sie, die Funktion außerhalb des Blocks zu definieren:

fib :: (Integral a) => Int -> Int 
fib x | x == 0 = 0 
     | x == 1 = 1 
     | x >= 2 = fib (x - 2) + fib (x - 1) 

main = print (fib 5) 

Wenn Sie darauf bestehen, die Funktion lokal auf die Definition (im Ausdruck, der durch Aussagen des do Block gebildet wird):

main = do 
    let 
     fib :: (Integral a) => Int -> Int 
     fib x | x == 0 = 0 
       | x == 1 = 1 
       | x >= 2 = fib (x - 2) + fib (x - 1) 
    print (fib 5) 

Hinweis wie let wird verwendet, um eine neue Variable an die Funktion, die Sie möchten, zu binden.

Verwandte Themen