2012-03-29 239 views
0

您好我是Haskell的新手,我在嘗試使此腳本運行時遇到問題。該腳本從命令行中讀取參數並在單獨的文本文件中找到它們。在文本文件輸出中查找並替換帶有星號的文字

E.G:cat.txt | ./red房屋大貓(在編譯器中)

它通過用星號(**)星號代替文本文件中的某些單詞。用於每個編輯單詞的星星數量應等於單詞中的字符數。

module Main where 

import System 
import Data.Char 
import Data.List 

lowercase :: String -> String 
lowercase = map toLower 

main = do 
arg1 <- getArgs 
txt <- getContents 
putStr (redact txt arg1) 

redact :: String -> String -> String 
redact input xWords = unlines [ work line | line <- lines input ] 
where work line = unwords [ foo word | word <- words line ] 
    foo w | lowercase(w) == lowercase(xWords) = convertWord w 1 
    | otherwise       = w 

convertWord Eq a => [a] -> [a] 
convertWord = map (const '*') 

然而,當我嘗試編譯此,GHCI返回錯誤:

redact.hs:13:38: 
    Couldn't match expected thye 'Char' with actual type '[Char]' 
    Expected type: String 
    Actual type: [String] 
    In the second argument of 'redact', namely 'arg1' 
    In the first of 'putStr', namely '<redact txt arg1>' 
Failed, module loaded: none. 

因此,代碼:

putStr (redact txt arg1) 

引起的問題。

非常感謝您的幫助,如果您可以改進代碼,那將是非常棒的。

編輯:

我想進入儘可能多的ARGS越好,它不事關你多少ARGS進入,我想:

(arg1:arg2:arg3:arg4:arg5:_) <- getArgs 

但我不得不進入EXACT 5個ARGS,不管我輸入多少參數都不重要。 我正在考慮使用某種循環,但我不確定?

再次感謝您的幫助。

回答

1

要讓它與多個參數一起使用,請使用getArgs。問題在於

foo w | lowercase(w) == lowercase(xWords) = convertWord w 1 
     | otherwise       = w 

,你一個字的小寫比較多字小寫。後者沒有定義,您想將它與xWords的每個的小寫字母進行比較。所以首先你需要把它們全部改爲小寫,這可以通過主redact txt (map lowercase arg1)而不是redact txt arg1來最有效地完成。那麼你需要確定一個讀字是列表xWords,這就是elem函數的用處。

foo w | lowercase w `elem` xWords = convertWord w 1 
     | otherwise     = w 

BTW,你也許應該不會調用此函數foo即使它只是一個局部的一個。

1

getArgs :: IO [String],打完arg1 <- getArgsarg1有型[String]:它包含傳遞給你的程序的所有的參數,如清單。但是您使用它作爲String,因此錯誤:GHC預計arg1String,但它是[String]

您可以模式匹配上這樣的結果:

arg1:_ <- getArgs 

這導致arg1包含列表的第一個元素,並丟棄列表的其餘部分。如果您不傳遞參數,則會導致運行時錯誤。當然,如果你想要更專業化的行爲(比如在沒有參數的情況下輸出錯誤),你可以使用更復雜的方法來提取第一個參數,比如case表達式。

至於改善你的程序走:

  • 可以使用的功能成分和map而非列表理解簡化work定義:work = unwords . map foo . words(讀:「在所有的元素映射foo他們「words,然後unwords)。

  • redact可以簡化爲redact input xWords = unlines . map work . lines $ input

  • lowercase(w)最好寫成lowercase w

但是你的程序看起來基本上沒什麼問題,除了一些古怪(如缺少::convertWord的類型簽名,附加1您傳遞給它的foo - 但有點古怪的縮進去,我想你在發佈之前編輯了代碼)。除非你明白他們是如何工作的,並且很舒適地編寫這樣的代碼,否則我不會做出前兩個變化。

+1

根據示例,使用_all_參數是OP實際需要的。 – leftaroundabout 2012-03-29 22:51:05

+0

@leftaroundabout:嗯,對。我被'arg1'的命名弄糊塗了。哦,希望我的其他建議對我有幫助。 – ehird 2012-03-29 22:52:22