4

配列を取得して反復するカスタム関数を作成しようとしています。すべての桁を出力し、同じ関数を再帰的に起動する必要がありますが、エラーが発生します。

入力`main'の解析エラー

コード:

firstitem n = if n /= [] n firstitem( tail n )


main = do
    print(firstitem [1,2,3])
4

2 に答える 2

11

最初の問題は、ifステートメントの構文が間違っていることです。あなたは書くべきです

firstItem n = if {- condition-}
    then {- do this -}
    else {- do that -}

第二に、関数が何をするべきかが明確でfirstItemはありません。リストの最初の項目を返すことになっているように聞こえますが、あなたの説明では、リストのすべての要素を反復処理したいように見えます。

次のように、反復と印刷を単一の関数に組み合わせることができます。

printAll xs = if null xs        -- If the list is empty
    then return ()              -- then we're done, so we quit.
    else do print (head xs)     -- Otherwise, print the first element
            printAll (tail xs)  -- then print all the other elements.

main = printAll [1,2,3]

リストが空の場合、関数は をnull返します。それ以外の場合は を返します。「これ以上処理するものがないので、今すぐ関数を停止し、結果を返さない」という文と考えることができます。3 行目と 4 行目には「do ブロック」が含まれています。do ブロックは基本的に、2 つのアクションを結合して 1 つのアクションにするちょっとした接着剤です。少しわかりやすくするために、中括弧を使用して記述できます。TrueFalsereturn ()print (head xs)printAll (tail xs)

do {
  print (head xs);
  printAll (tail xs)
}

実際には必要ありませんが、インデントはあなたが何を意味するかを指定しています。

これで問題は解決しますが、少し面倒です。結局、Haskell は美しい言語であるはずなので、コードを美しくしましょう! パターン マッチングを使用して、リストを先頭と末尾に引き離した方がよいでしょう。

printAll []     = return ()
printAll (x:xs) = do print x
                     printAll xs

それはずっと良いです。しかし、それはよりモジュール化される可能性があります。ちょっと、入力としてアクションを取り、リストのすべての要素に対してそのアクションを実行する汎用関数を作成できます。

repeatedly f []     = return ()
repeatedly f (x:xs) = do f x
                         repeatedly f xs

printAll xs = repeatedly print xs

それはいいですね。しかし、実際には、これを行う関数が既にあります。それは呼び出されmapM_(これと呼ばれるのには十分な理由がありますが、ここでは説明しません)、Control.Monadモジュール内にあります:

import Control.Monad

printAll xs = mapM_ print xs

実際には、xs引数を省略することができ、コンパイラはそれがそこにあるはずだと推測できます。

printAll = mapM_ print

最後に、あなたのコードは美しいです。それが少し役立つことを願っています。

于 2012-10-16T07:37:25.560 に答える
1

Haskellではif常にelseブランチも必要です。また、が欠落していthenます。つまり、形式の何かが必要ですif CONDITION then TRUE_VAL else FALSE_VAL

ifパターンマッチングを使用することで、完全に回避できます。

実行中の進行状況を印刷するには、Writerモナドを使用できます。

于 2012-10-16T07:29:29.267 に答える