配列を取得して反復するカスタム関数を作成しようとしています。すべての桁を出力し、同じ関数を再帰的に起動する必要がありますが、エラーが発生します。
入力`main'の解析エラー
コード:
firstitem n = if n /= [] n firstitem( tail n )
main = do
print(firstitem [1,2,3])
最初の問題は、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 つのアクションにするちょっとした接着剤です。少しわかりやすくするために、中括弧を使用して記述できます。True
False
return ()
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
最後に、あなたのコードは美しいです。それが少し役立つことを願っています。
Haskellではif
常にelse
ブランチも必要です。また、が欠落していthen
ます。つまり、形式の何かが必要ですif CONDITION then TRUE_VAL else FALSE_VAL
。
if
パターンマッチングを使用することで、完全に回避できます。
実行中の進行状況を印刷するには、Writer
モナドを使用できます。