2017-10-26 6 views
3

私は最初にPythonで関数型プログラミングを手に入れた後、Haskellを学び始めました。1行のコードでIntを読み取るには?

まず最初に、悪い習慣は事実上すべてのプログラミング言語であり、純粋に教育以外の深刻な目的でこれを使用しないことを約束します。それは...

私が一番好きだったことの1つは、コードを読めるようにしながら、ただ1行のコードを使って関数を書くというエレガンスでした(C/C++スタイルのもの

私はトラフの質問を見て、少なくともいくつかの異なったhaskellチュートリアルや文書を試してみましたが、いくつかは近づいてきましたが、 1行のコードでIntを使用できます。

質問のために、私はキーボードのためにIntを読んで "Hello World!"それは何度も(HackerRankから恥知らずに盗まれた)。

私はgetLinereadLnreadを使用してみましたが、物事には、唯一のIO操作が頑固に私にエラー私は別の声明に入れていなかったすべての時間を与えて立ち往生したままに、表記を行う代わりに、>>=に見えました。

私が試してみました事のいくつか:

main :: IO() 
main = readLn :: IO Int >>= \n -> mapM_ putStrLn $ replicate n "Hello World!" 

が得られます。そして、

parse error on input ‘\’ 

main = readLn >>= \n -> read n :: Int >>= \n -> mapM_ putStrLn $ replicate n "Hello World!" 

は同じエラーを与えます。

と同じ:私は正確

main = getLine >>= \n -> read n :: Int >>= \n -> mapM_ putStrLn $ replicate n "Hello World!" 

何を理解していないのですか?前もって感謝します!

+0

または 'readLn >> = sequence_です。フリップレプリケート(putStrLn "Hello World") ' (輸入不要) –

答えて

6

タイプ宣言と式を混在させています。それは次のようになります。

main = (readLn :: IO Int) >>= \n -> mapM_ putStrLn $ replicate n "Hello World!" 

あなたの問題はブラケットなしで、コンパイラが型宣言を読んでいたかのように解析し続けることだったので、それは\渡って走って捕まってしまいました。

ただし、この型宣言は推測されます(replicate :: Int -> a -> [a]以降)ので不要です。 削除します!一般的に

main = readLn >>= \n -> mapM_ putStrLn $ replicate n "Hello World!" 

しかし、それは完全にこの問題を回避し、ちょうどdo -notationを使用することがはるかに良いです。ハスケルでのこのような「ゴルフ」はとても楽しいですが、明確で保守可能なコードを作る方法ではありません。

import Control.Monad (replicateM_) 

main = do 
    n <- readLn :: IO Int     -- Type optional here. 
    replicateM_ n $ putStrLn "Hello World!" -- A more concise expression. 
+0

ありがとう!それは意味をなさない、私はhaskellかなりtypecastingのメカニズムがあると思います。 –

+0

@RaresDima本当ですか?一般的には、すべての型を宣言することなくHaskellを書こうとします。コンパイラがそれを動作させることができないときにのみ行います。 GHCは、あなたが慣れ親しんだほとんどのコンパイラよりスマートです! – AJFarmar

+4

@RaresDimaしかし、一般に、すべてのトップレベル関数にタイプシグネチャを与えるのが良い方法です。私はまた 'let'または' where'節で重要な定義にタイプシグネチャを与えることを好みますが、時には 'ScopedTypeVariables'言語拡張を使う必要があります。 – dfeuer

関連する問題