你好我是Haskell的新手,我在尝试让这个脚本工作时遇到了问题。此脚本从命令行读入参数,并在单独的文本文件中查找。
E.G:cat.txt | ./redact house big cat(编译器中)
它通过用星号(**)星号替换它们来编辑文本文件中的某些单词。每个编辑单词使用的星号数应该等于单词中的字符数。
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,我输入的args数量无关紧要。 我在考虑使用某种循环,但我不确定?
再次感谢您的帮助。
答案 0 :(得分:1)
getArgs :: IO [String]
,因此在arg1 <- getArgs
之后,arg1
的类型为[String]
:它包含所有传递给您的程序的参数,作为名单。但是您将其用作String
,因此错误:GHC预期arg1
为String
,但它是[String]
。
您可以对结果进行模式匹配,如下所示:
arg1:_ <- getArgs
这导致arg1
包含列表的第一个元素,并丢弃列表的其余部分。如果不传递参数,则会导致运行时错误。当然,如果您想要更专业的行为(比如,在没有给出参数的情况下打印错误),您可以使用更复杂的方法来提取第一个参数,例如case
表达式。
对于您的计划的改进:
您可以使用函数组合和work
而不是列表推导来简化map
的定义:work = unwords . map foo . words
(读取:“map foo
覆盖所有words
的元素,然后是unwords
他们“。
redact
可以简化为redact input xWords = unlines . map work . lines $ input
。
lowercase(w)
最好写成lowercase w
。
但是你的程序对我来说看起来基本上没问题,除了一些奇怪之处(比如::
类型签名中缺少convertWord
,你在{{{{}}传递给它的额外1
1}} - 但是通过稍微不稳定的缩进,我猜你在发布之前编辑了代码)。我不会做出前两个更改,除非你了解它们是如何工作的,并且很乐意编写这样的代码。
答案 1 :(得分:1)
要使其与多个参数一起使用,请使用getArgs
。问题在于
foo w | lowercase(w) == lowercase(xWords) = convertWord w 1
| otherwise = w
将一个单词的小写字母与多个单词的小写字母进行比较。后者未定义,您希望将其与xWords
的的每个的小写字母进行比较。首先,您需要将它们全部设置为小写,通过从主redact txt (map lowercase arg1)
调用而不仅仅是redact txt arg1
来最有效地完成。然后,您需要确定读取的单词是 in 列表xWords
,这就是elem
函数的用途。
foo w | lowercase w `elem` xWords = convertWord w 1
| otherwise = w
顺便说一下,即使它只是本地函数,也不应该调用此函数foo
。