2016-05-04 12 views
0

Итак, я играл с Haskell за последние пару дней, и решил, что сделаю базовое определение последовательности Фибоначчи. Так что я написал этот код:Haskell Says My Guard имеет ошибку анализа

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) } 

И я получаю сообщение об ошибке, говорящее:

4:17: parse error on input `|' 

Я подозревал, что на вкладке ошибки, поэтому я попытался все пробельные исправить я мог найти, но я просто не могу найти что не так!

EDIT: Так что я сделал то, что предложил людям, и у меня есть этот код прямо сейчас:

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) 

И я получаю ту же ошибку.

+0

Любого почему кладут подпись типа и функции в блок do? – jakubdaniel

+0

Я не знал, что делаю. – ThePhillipParadox

ответ

1

Вы также можете определить fib на местном уровне до main за пределами блока . Имейте в виду, что do является синтаксическим сахаром для использования различных монадических функций привязки, и поэтому принятый внутри него синтаксис не совсем такой же, как и принятый за его пределами. И, на самом деле, ваш main даже не требует блока do, потому что вы просто вызываете print, а не цепляете любые действия IO.

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

Или вы могли бы использовать where:

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

Они же, вопрос только где местное связывание на самом деле идет. let .. in дает новый блок, в котором новые привязки находятся в области видимости, тогда как where делает свои привязки доступными в рамках функции, к которой она привязана.

Если, как кажется, в конце концов, вероятно, вы хотите do блока, а поэтому вы можете сделать несколько IO действий, вы можете просто положить, что вместо вызова print, например, так:

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

Вы должны определить fib за пределами main, а не внутри него. И тогда вы должны удалить хотя бы один из do s с main.

+1

'do' не проблема, я бы сказал, вы можете их вложить. Но если вы хотите связать переменную в блоке do, вам нужно использовать 'let'. – jakubdaniel

+0

Конечно, но они все еще плохие и странные. – amalloy

+0

Я переместил 'fib :: (Интеграл a) => Int -> Int' наружу« main », но я получаю ту же ошибку. – ThePhillipParadox

3

Проблема заключается в том, что вы пытаетесь определить функцию в блоке do, фактически не используя какую-либо конструкцию для определения вещей (например, let).

Попробуйте определения функции за пределами блока:

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) 

Если вы настаиваете на определении функции локально (внутри выражения, которое формируется отчетность do блока):

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) 

Уведомление как let используется для привязки новой переменной fib к функции, которую вы хотите.