0

宿題の一部です。入力から空の行まで情報を読み取る関数を作成する必要があります。その関数の後、1 番目、3 番目、5 番目 ... の行記号を 1 つの String として配置し、2 番目、4 番目 ... を別の String として配置します。署名はcombine :: IO (String , String)

リストを引数として取り、1,3,5.. を 1 つStringに、2,4,6 シンボルを別の.. に配置する関数を作成しましたString。関数はここにあります:

intotwo (x : xs)
   = let
      (us , vs)
         = intotwo xs
   in
   (x : vs , us)
intotwo _
   = ([] , []) 

また、入力を読み取るコードを作成しました: ここにあります:

combine
   = do
      lines <- getLine
      if null lines
         then return ([], [])
         else do
            linesagain <- combine
            return --what should I return?

宿題を終わらせるのを手伝ってくれる人はいますか (オプション: ヒントを教えてください)。

4

2 に答える 2

5

あなたの問題を解決するためのヒントをいくつかお伝えします。

まず、定義するすべての関数に型を与えることは非常に役立ちます。これにより、関数が実行していると思われることを実行していない場合、コンパイラはすぐに通知できます。また、プログラムのさまざまな部分を結合する必要がある場合にも役立ちます。

第 2 に、関数ごとに 1 つの問題だけを解決することは非常に良い考えです。あなたの intotwo 関数はこれによく従い、リストを非常にうまく分割する仕事をします。ただし、結合関数は多すぎるように見えるため、書き込みが難しくなります。その関数を 2 つの小さな関数に分割します。

最後に、 という非常に便利な特殊関数がありundefinedます。これはあらゆる型にマッチし、関数を書くのに役立ちます。秘訣は、関数全体が未定義に等しい状態 (およびコンパイルは実行時にクラッシュする) から開始し、目的の動作を行い、未定義がなくなるまで関数を徐々に改善することです。

まず、intotwo 関数に型シグネチャを追加します。タイプは[a] -> ([a], [a])です。

次に、空の行に到達するまで入力から行を読み取り、読み取った行のリストを返す関数を作成します。この関数の型は次のとおりです。

readLinesUntilEmpty :: IO [String]
readLinesUntilEmpty = undefined

これをほぼ行う実装は次のとおりです。

readLinesUntilEmpty = do
  nextLine <- getLine
  rest <- readLinesUntilEmpty
  return (nextLine : rest)

ただし、これは読み取りを停止することはありません ( nextLine が空であるかどうかがチェックされないことに注意してください)。

次の関数は、これを行う方法を示しています (ただし、実装の一部は省略しています)。

readLinesUntilEmpty = do
  nextLine <- getLine
  case nextLine of
    "" -> do
      undefined -- TODO fix me
    _ -> do
      undefined -- TODO fix me

そこから残りを把握できるはずです。

次に、intotwo 関数は文字列の 2 つのリストを返しますが、それらを再び結合する必要があります。たとえば["this", "that"]、 に変わる必要があります"this\nthat"。そのような関数のタイプは次の[String] -> Stringとおりです。

joinLines :: [String] -> String
joinLines = undefined -- TODO

これは inttotwo 関数よりも書きやすい関数なので、問題ないはずです。

最後に、これら 3 つの関数をリンクして結果を得ることができます。

combine :: IO (String, String)
combine = do
  lines <- readLinesUntilEmpty
  let (oddLines, evenLines) = intotwo lines
  return $ (joinLines oddLines, joinLines evenLines)
于 2012-06-10T15:25:21.907 に答える
0

複数の文字列を読み取る必要があるため、再帰的な入力が必要です。または、getContents を使用することもできますが、インタラクティブな I/O に適しているかどうかはわかりません。このようなもの:

combine = getContents
          >>= return . intotwo
于 2012-06-10T14:28:33.787 に答える