2017-02-07 6 views
1

私はHaskellを初めて使用しています。私は入力文字列(a)を読んでいて、内部に文字(e)が見つかると文字列を返したいと思います。今、私の全体のソースコード:IO()の代わりに[Char]を取得するString

a = "b,b,b,b/b,b,b/b,b,b,b/e,e,e/w,w,w,w/w,w,w/w,w,w,w" 
n = length a 

simpleCase n = 
    case n of 
     'a' -> "hey cutie" 

eLoopCase i = 
    if i < n 
     then do 
      let char = a !! i 
      case char of 
       'e' -> putStr $ "(" ++ "found an e" ++ ")," 
       'w' -> return() 
       'b' -> return() 
       ',' -> eLoopCase (i+1) 
       '/' -> eLoopCase (i+1) 
      if (char == ',' || char == '/') == False 
       then eLoopCase (i+1) 
       else return() 
     else return() 

simpleCaseは私に文字列をバック与えるがeLoopCaseは私のIO()バックを提供します。それは動作しますが、私はeLoopCaseがStringを返すようにしたいので、私はそれに取り組むことができます。

:t simpleCase 
simpleCase :: Char -> [Char] 
:t eLoopCase 
eLoopCase :: Int -> IO() 

私は私の理解が終わるところこれは、これはモナド、then doputStrとは何かを持っていることを理解しています。 doを削除すると、解析エラーが発生します。

+3

タイプの署名をお願いします。そして、問題に関連していない事例句のいくつかを削除しないのはなぜですか? – leftaroundabout

+1

ここにあなたのコードをすべて入れないで[MCVE](http://stackoverflow.com/help/mcve)を作ってください。 – wizzup

+0

Not * nomads *しかし* monads *。 –

答えて

3

ハスケルを学ぼうと思ってうれしいです。 eLoopCaseよりも多くのことができます。私はあなたにどのように説明しますが、最初にあなたの元の質問にあった問題とその解決方法を説明します。

eLoopCaseはもともと書かれているように、タイプInt -> IO()です。つまり、Intを受け取り、入力出力アクションを返す関数です。 IOW、タイプは、あなたがそれに数字をつけたら、何かとすることを伝えます。コードを見ると、何かが文字列を印刷しているだけであることがわかりますが、ほとんど何でもあった可能性があります。

答えでは、を書き換えて、++演算子を介して直接putStr経由で端末に出力するのではなく、文字列を直接作成しました。これは、書き換えられた関数がその型を持つ理由です。また、return()ステートメントが不要になった理由についても説明します。これは、「()値を返す間に何もしないでください」というIOアクションです。

少しクリアすることを願っています。つまり、eLoopCaseは大幅に改善することができます。

Haskellプログラムは、制御ロジックがデータ構造と一致するときに効率的に書き込まれます。たとえば、このプログラムはリストを反復しています。リストは、以下の宣言で見られるように、空のリストまたは要素であるデータと、より多くのリストであるデータとして定義されます。

data List a = [] 
      | a : List a 

したがって、リストを反復するプログラムは、2つのコンストラクタの決定に基づいています。良い - ([Char]ため同義語Stringを使用して)、例えば、eLoopCaseは、それがもはやハード関数の本体にコード化されないように、入力としてaを供給する

eLoopCase' :: String -> String 
eLoopCase' []  = "" 
eLoopCase' (a:as) = evalCase a ++ eLoopCase' as 

evalCase a = case a of 
    'e' -> "(" ++ "found an e" ++ ")," 
    'w' -> "" 
    'b' -> "" 
    ',' -> "" 
    '/' -> "" 
    _ -> "" 

注意eLoopCase'ニーズのように書き換えることができます。もの。インデックスiと、!!eLoopCase (-1)に電話してみてください)の使用に起因するエラーもありません。

eLoopCase'のような再帰関数を記述することをお勧めします。プログラミングの進化は、あなたがそのループで何をしようとしているのかを見て、適切なパターンを適用することです。

たとえば、リスト内のすべての要素を特定の関数で評価する場合は、mapを使用します。具体的にmap evalCaseは一緒にすべてのこれらのリストを追加するconcatを使用し、その後、文字列のリストに文字のリストから行く:

eLoopCase'' = concat . map evalCase 
+0

を探しています。頭が上がったように、投稿したコードはコンパイルされません。 – Erik

+0

ありがとう、私は使用すると思ったが、できなかった多くの機能を使用しました! – Xui

+0

ありがとうございました@erik、修正済みです。 –

0

実際に私自身の質問に答えました。次のように動作しているようです:

a = "b,b,b/b,b,b/b,b,b,b/e,e,e/w,w,w,w/w,w,w/w,w,w,w" 
n = length a 

eLoopCase i = 
    if i < n 
     then 
      case a !! i of 
       'e' -> "(" ++ "found an e" ++ ")," ++ eLoopCase (i+1) 
       'w' -> "" ++ eLoopCase (i+1) 
       'b' -> "" ++ eLoopCase (i+1) 
       ',' -> eLoopCase (i+1) 
       '/' -> eLoopCase (i+1) 
     else "" 

私はまだ何が起こったのか不思議です。

+0

何が起こったのですか?haskellはpure関数から "printf debugging"に敵対します。 –

4

eLoopCaseは、すべての「末尾」にreturn()があるため何も返しません。あなたのコードで

a :: String 
a = "b,b,b,b/b,b,b/b,b,b,b/e,e,e/w,w,w,w/w,w,w/w,w,w,w" 

eLoopCase :: String -> IO String 
eLoopCase [] = return [] 
eLoopCase (x:xs) 
    | x == 'e' = do 
     putStrLn "(found an e)" 
     return [x] 
    | x == ',' || x == '/' = 
     eLoopCase xs 
    | x == 'w' || x == 'b' = do 
     rest <- eLoopCase xs 
     return (x : rest) 
    | otherwise = do 
     putStrLn ("Encountered invalid character: " ++ show x) 
     return [] 

一般的な問題:

  • プログラムあなたに私はあなたがこの(x == 'w' || x == 'b'ブランチで再帰呼び出しの結果に現在の文字を追加する通知)のようなものの後だと思います書いたスタイルで非常に不可欠です。これは、私がハスケルを書いている間にあなたが離れようとすることを強く望むものです。
  • !!を使用してインデックス作成のリストでのパターンマッチングを推奨します。

私が提供した機能には、それ自体の欠陥があることに注意してください。それは、それに提供された文字列が2つの異なる文字から構成されることを前提としています。それを改善する方法は、otherwiseブランチをガードに追加することです。 (編集:上のスニペットに追加)

私は、この機能が本当にIOに依存している必要はないことを指摘しておく価値があると思います。 EitherMaybe、およびWriterのようなエラー処理/レポートのための他の「純粋な」代替案を見てください。

+0

ありがとう!パターンマッチングと命令的スタイルを調べます。私は、eを見つけた後、リスト全体を繰り返し処理する方法を探していました。例えば、私が投稿した答えは '(eが見つかりました)、(eが見つかりました)、(eが見つかりました)、'を返します。また、eLoopCaseのタイプはIO Stringで、私は[Char] – Xui

関連する問題