2013-02-03 17 views
8

私はちょうどhaskellを学び始めています。それは私がよく慣れていたもの(Cスタイルの言語)とはまったく異なる考え方です。ユーザー入力回数を入力できるようにするhaskell方法はありますか?

とにかく、私はユーザー入力を受け取る必要があります。それは形式で来るでしょう

2 
10 
20 

例えば、形式は最初の行に続く行数です。私の最初の考えは、私が最初の行を読んでから、その回数だけループを走らせるということでした。これはハスケルですが!私が知る限り、ループは不可能です。

私の次の考えは、最初の入力行を使用して、続くn個の番号のリストを記入することでした。私はこれをどうやってやるのか分かりません。私はそれを理解するために私が何を探しているのか、私が確信していないので私はここにいる。

私にこれを行うためのhaskell方法を示すために事前に感謝します。それはこれまでのところ厳しいですが、 "啓発"された人からの批評を聞くので、自分自身で言語を習うことはできません。

一度はうまく動作するが、最初の行に続く2行目からn行目のそれぞれに対して一度実行する必要があるコードを次に示します。

l n = (-1)^n/(2*(fromIntegral n)+1) 
a m = sum [l n | n <- [0..(m-1)]] 
main = 
    do b <- readLn 
     print (a b) 

(また、私は自分のコードに作ることができ、他の改良点があるかどうかを聞くのが大好きだが、この特定の場合には、それが可能な文字の数が最も少ないの問題点を解決するための競争のためである。I他の人が同じ問題に対する答えを検索しようとしている場合に、もっと具体的にしたいとは思わないでください)。

EDIT:everyones answersに感謝します。私は最終的に私がそれを望んでいた方法で行動しました。私は後世のために以下のコードを書いています。悲しいことに、飛行色のテストケースに合格したにもかかわらず、テストした実際のデータは異なっていて、私が教えてくれたのは「間違った答え」だということです。このコードは「機能しますが、正しい答えを得られません。

import Control.Monad 
l n = (-1)^n/(2*(fromIntegral n)+1) 
a m = sum [l n | n <- [0..(m-1)]] 
main = 
    do b <- readLn 
     s <- replicateM b readLn 
     mapM_ print [a c | c <- s] 
+0

多分丸め誤差ですか?たぶん、すべての有理数を使って、最後の浮動小数点数に変換しようとします。( 'import Data.Ratio'、' l :: Integer - > Rational'、 'mapM_(print。realToFrac)') – luqui

+1

丸め誤差。私がこれをした後でさえそれは間違っていた。私の問題は、私が正確すぎるということでした。私は精度の小数点以下16桁のように与えていたが、彼らは15桁しか欲しかった。これを行うためのハズレの方法がありますか?この問題はあなたが実際の生活の中で実行するものではありません。ほとんどの企業は精度が低く、できるだけ少ない文字を要求することはありません(これらの恐ろしい1文字の変数名につながります) – maccam912

+0

ループを作成するだけでリストを構築する必要はありません: '' main = do {b < - readLn; replicateM_b(do {c < - readLn; print(a c)})} ''。または、ループは再帰で直接コーディングできます: 'main = readLn >> = loop'; 'loop n | n <1 = return()|そうでなければ= readLn >> =(print。a)>> loop(n-1) '。 –

答えて

10

まず、haskellでうまくループできます。それはいつも起こります。あなたはそれのための構文の構造を持っていないので、それらのための構文がありません。

ほとんどの場合、一般的な汎用ループがライブラリに入れられます。この場合、必要なループは標準ライブラリーのモジュールControl.Monadにあります。それはreplicateMと呼ばれています。これは、タイプ署名Monad m => Int -> m a -> m [a]です。あなたのケースでこの署名を特化するには、タイプはInt -> IO Int -> IO [Int]です。最初の引数はループする回数です。 2つ目は、各ループで実行するIOアクションです。関数の結果は、入力のリストを生成するIOアクションです。

doブロックにinputs <- replicateM b readLnを追加した場合、inputsという名前のリストが、bの入力行の値を最初のものに含むスコープに入れられます。これらの行にソリューション関数をマップすることができます。

1

を作成できます。ここで、nは読み込む行数です。毎回nから1を引いてこれを再帰的に呼び出します。私はハスケルのノブでもあるので、これは最良のアプローチではないかもしれません。しかし、それでも動作するはずです。

6

Carlのソリューションは機能しますが、やや不透明です。ただ、空を与え、

readLines :: Int -> IO [Int] 
readLines 0 = return [] 
readLines n = do 
    x <- fmap read getLine 
    rest <- readLines (n-1) 
    return $ x : rest 

readSomeNumberOfLines :: IO [Int] 
readSomeNumberOfLines = do 
    n <- fmap read getLine 
    readLines n 

何あなたは、本質的に明白なベースケースを定義しているされてreadLinesで、ここでやっている(0物事を読むために:あなたが出て、それを書きたい場合は、このような何かを行うことができますリスト)と再帰的なケース(n個の物を読み、1つの物を読んだり、n-1個の物を読んだり、一緒に結合する)。

2

私はあなたが何をしたいのか正確わからないんだけど、整数を読んで、nおよびあなたが何か行うことができ整数として、次のn行する:最後に

import Control.Monad 

-- read n, then sum integers read from the next n lines 
test = do n <- readLn 
      xs <- replicateM n readLn 
      return $ sum xs 

return $ sum xsをもちろん実質的ではありません。もしそこになければ、testの明示的な型署名が必要でしょう。

これらの機能を理解できない場合は、hoogleと入力してください。

関連する問題