2016-04-26 4 views
-1

私は自分のプログラムに問題があります。プログラムは1行に1行のファイルを読み込まなければならず、それが回文で、すべての単語の長さであると言う必要があります。私はとき、私は正しく私のプログラムを完了するために、助けてください:)私のpalidromプログラムをより良くするにはどうすればいいですか?

+0

http://codereview.stackexchange.com/にもっと適しているかもしれません。 –

答えて

2

まず、やるブロック内Haskellで非常に非常に新しいですし、これだけを持っているが、それは:(

main = do 
    inhalt <- readFile "palindrom.txt" 
    laengeWort = length inhalt 
    if istPalindrom inhalt 
    then putStrLn (inhalt ++ " ist ein Palindrom und hat die Laenge "++ laengeWort 
    else putStrLn (inhalt ++" ist kein Palindrom und hat die Laenge " ++ laengeWort) 

isPalindrom w = w == reverse w 

仕事doesntの変数を導入するには、letというキーワードを使用する必要があります。 (またはファイルを読み込むときに、あなたが行ったように、モナドの値を抽出する際<-を使用しています。)

laengeWort = length inhalt 

laengeWort変数の型Intであり、第二に

let laengeWort = length inhalt 

となり、あなたが使用する必要がありますshowこれを文字列に変換する関数。 (いくつかの他の言語が行うようにHaskellは文字列への型の暗黙的な変換を持っていません。)

は最後に、あなたはistPalindrome としてisPalindromを誤って入力して、あなたは文法的に正しい解決策があるthen putStrLn (

から始まる括弧を閉じるのを忘れて(私は英語に翻訳):単一の文字列/単語であるかのように

main = do 
    contents <- readFile "palindrom.txt" 
    let contentLength = length contents 
    if isPalindrome contents then 
    putStrLn (contents ++ " is a palindrome of length "++ show contentLength) 
    else 
    putStrLn (contents ++" is not a palindrome, it has the length " ++ show contentLength) 

また、このソリューションは、ファイル全体に作用します。あなたの説明から、あなたはそれぞれの行を別の言葉として扱うように思えます。これを行うには、lines関数を使用して行ごとに内容を分割し、partitionを使用して、単語を回文である単語とそうでない単語にフィルタリングします。次に、mapM_を使用して各単語を印刷できます。 (それは言葉の順序を保持しませんが)ここではかなり簡潔な例です:

import Data.List (partition) 
main = do 
    contents <- lines `fmap` readFile "palindrom.txt" 
    let (palins,notPalins) = partition isPalindrome contents 
    mapM_ (\w -> putStrLn $ "the word " ++ w ++ " is a palindrome of length " ++ show (length w)) palins 
    mapM_ (\w -> putStrLn $ "the word " ++ w ++ " is not a palindrome, it has length" ++ show (length w)) notPalins 

isPalindrome w = w == reverse w 

私は 上readFileの結果を(純粋な文字列をとる)ライン機能をマッピングするために「FMAP」を使用(返しますIOモナドの文字列)、IOモナドの文字列のリストを取得し、 '< - '演算子はモナドからそのリストを抽出します。

rawData <- readFile "palindrom.txt" 
let contents = lines rawData 
2

問題はあなたが単一String"palindrom.txt"の内容全体を読みますreadFileを、使用していることである: それは言うに相当します。ファイルの内容を行に分割し、isPalindromを行に適用する必要があります。これはlines組み込み関数で行い、mapM_を使用します。それはクリーナーあなただけmapM_スワップ引数の順序である、Control.MonadからforM_を使用することができますようにするには:それはより多くの他の言語からのforループのように見えるので、

mapM_ :: Monad m => (a -> m b) -> [a] -> m() 
forM_ :: Monad m => [a] -> (a -> m b) -> m() 

を私はほとんどの時間をそれを好みます。だからあなたのコードは、私もそれ少しきれいにすると、ラインが少し短くするif文の前にあることまでputStrLnを浮かべ

import Control.Monad (forM_) 

main = do 
    inhalt <- readFile "palindrom.txt" 
    forM_ (lines inhalt) (\wort -> do 
     let laengeWort = length wort 
     putStrLn (if istPalindrom wort 
      then wort ++ " ist ein Palindrom und hat die Laenge " ++ show laengeWort 
      else wort ++ " ist kein Palindrom und hat die Laenge " ++ show laengeWort 
     ) 
    ) 

istPalindrom w = w == reverse w 

ようになります。

構文にはいくつかの問題がありましたが、初心者の方や、ほとんどのチュートリアルが母国語でない場合は、かなり寛容です。

macheNachricht :: String -> String 
macheNachricht wort = 
    let nachricht = if istPalindrom wort 
      then " ist ein Palindrom" 
      else " ist kein Palindrom" 
     laengeWort = show (length wort) 
    in wort ++ nachricht ++ " und hat die Laenge " ++ laengeWort 

を次にmain

main = do 
    inhalt <- readFile "palindrom.txt" 
    forM_ (lines inhalt) (\wort -> putStrLn (macheNachrict wort)) 

のようになります。これは、Haskellのを使用してさらに低減することができます。もう少し、私はおそらく別の関数に書式メッセージを引き出すだろう、このコードをクリーンアップするために

関数合成演算子.は、

f . g = \x -> f (g x) 
と定義されています

これは我々がforM_に2番目の引数として\wort -> putStrLn (macheNachricht wort)を持っているものを正確であるので、私達はちょうどputStrLn . macheNachrichtとしてそれを書くことができます。

main = do 
    inhalt <- readFile "palindrom.txt" 
    forM_ (lines inhalt) (putStrLn . macheNachricht) 

(申し訳ありませんmacheNachrichtとしてドイツへmakeMessageの私の翻訳が少し不正確である場合は、私がまだ自分自身でドイツ語を学び始めたばかりで、まだあまり良くはありません。)

関連する問題