我写了这段代码:
toCouplesFile = do inputFile <- openFile "deletedId.csv" ReadMode
outputFile <- openFile "couples.txt" WriteMode
readAndChange inputFile outputFile
readAndChange i o = do iseof <- hIsEOF i
if iseof then (return o)
else do line <- hGetLine i
hPutStrLn o (show (extractNameAndId line))
readAndChange i o
我想知道我是否可以仅使用一个函数重写此代码,使用类似于此模式的内容:
function x = do ...
label
.....
if ... then label else exit
最佳答案
通过以不必要的命令方式进行编程,您正在使生活变得困难。您正在使用漂亮的 Haskell 语言进行编程,并且正在寻找 goto
构造!
为什么不只是 import Control.Applicative (<$>)
和写
readAndChange' = writeFile "couples.txt" =<<
unlines.map (show.extractNameAndId).lines <$> readFile "deletedId.csv"
(是的,这几乎是一个单行。它是干净的、功能性的风格,并且没有被读写行的机制弄乱。尽可能多的处理是在纯代码中完成的,只有输入和输出是基于 IO 的。)
说明:
这里
unlines.map (show.extractNameAndId).lines
通过将输入切割成行来处理您的输入,应用 extractNameAndId
然后 show
给每一个使用 map
,然后使用 unlines
将它们重新组合在一起.unlines.map (show.extractNameAndId).lines <$> readFile "deletedId.csv"
将读取文件并应用处理函数。 <$>
fmap
的语法令人愉快.writeFile "couples.txt" =<< getanswer
与 getanswer >>= writeFile "couples.txt"
相同- 得到上述答案,然后将其写入文件。试试写
greet xs = "hello " ++ xs
然后在 ghci 中为了好玩而做这些greet "Jane" -- apply your pure function purely
greet $ "Jane" -- apply it purely again
greet <$> ["Jane","Craig","Brian"] -- apply your function on something that produces three names
greet <$> Just "Jane" -- apply your function on something that might have a name
greet <$> Nothing -- apply your function on something that might have a name
greet <$> getLine -- apply your function to whatever you type in
greet <$> readFile "deletedId.csv" -- apply your function to your file
最后一个是我们如何使用
<$>
在 readAndChange
.如果里面有很多数据删除Id.csv 你会想念你好,但当然你可以这样做
greet <$> readFile "deletedId.csv" >>= writeFile "hi.txt"
take 4.lines <$> readFile "hi.txt"
查看前 4 行。
所以
$
允许你在你给它的参数上使用你的函数。 greet :: String -> String
所以如果你写 greet $ person
, person
必须是 String
类型, 而如果你写 greet <$> someone
, someone
可以是任何产生 String
的东西- 字符串列表,一个 IO String
, Maybe String
.从技术上讲,someone :: Applicative f => f String
,但你应该先阅读类型类和应用仿函数。 Learn You a Haskell for Great Good 是一个很好的资源。更有趣的是,如果你有一个有多个参数的函数,你仍然可以使用可爱的 Applicative 风格。
insult :: String -> String -> String
insult a b = a ++ ", you're almost as ugly as " ++ b
尝试
insult "Fred" "Barney"
insult "Fred" $ "Barney"
insult <$> ["Fred","Barney"] <*> ["Wilma","Betty"]
insult <$> Just "Fred" <*> Nothing
insult <$> Just "Fred" <*> Just "Wilma"
insult <$> readFile "someone.txt" <*> readFile "someoneElse.txt"
在这里您使用
<$>
后功能和<*>
在它需要的参数之间。它的工作原理起初有点令人兴奋,但它是编写有效计算的最实用的风格。接下来阅读 Applicative Functors。他们很棒。
http://learnyouahaskell.com/functors-applicative-functors-and-monoids
http://en.wikibooks.org/wiki/Haskell/Applicative_Functors
关于haskell - 在 do block 内迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12376623/