2016-05-04 11 views
0

これまでの数日間、Haskellと遊んでいたので、フィボナッチシーケンスの基本的な定義をすることにしました。だから私はこのコードを書いた:Haskellは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 `|' 

ので、私は、私は見つけることができるすべての空白文字の修正を試みたが、私は見つけることができませんどうしましたか!

編集:だから私は人々が提案し何をした、と私は今、このコードを持っている:

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

ブロックの外側にあるmainにローカルでfibを定義することもできます。 doはさまざまなモナディックバインディング関数を使用するための構文的な砂糖であるため、その内部で受け入れられる構文は外部で受け入れられる構文と全く同じではないことに注意してください。実際には、にはIOアクションを連鎖させるのではなく、printを呼び出すだけで、doブロックは必要ありません。

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は、バインディングを、それが接続されている関数のスコープ内で使用できるようにします。最終的にはそう思えるよう複数IOのアクションを行うことができますので、あなたにもdoブロックをしたいですか、場合

、あなただけそうのように、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

mainの外側にfibを定義する必要があります。そしてmainからdoのうち少なくとも1つを削除する必要があります。

+1

'do'sは私が言っている問題ではない、あなたはそれらを入れ子にすることができます。しかし、doブロック内の変数をバインドする場合は、 'let'を使用する必要があります。 – jakubdaniel

+0

確かに、彼らはまだ悪く奇妙です。 – amalloy

+0

'fib ::(Integral 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) 

お知らせどのように新しい変数fibを目的の関数にバインドするにはletを使用しますか?

関連する問題