我正在学习Haskell,我正在尝试编写一些只读取文件并使用该lines函数创建行列表的代码.例如,我有一个名为的文件data.txt包含以下行:
this is line one
another line
and the final line
Run Code Online (Sandbox Code Playgroud)
这是我试图用来将这些数据读入列表并将其打印到屏幕上的代码:
import System.IO
import Control.Monad
main = do
let list = []
handle <- openFile "data.txt" ReadMode
contents <- hGetContents handle
let myLines = lines contents
list = listLines myLines
print list
hClose handle
listLines :: [String] -> [String]
listLines = map read
Run Code Online (Sandbox Code Playgroud)
生成的代码编译,但不生成任何输出.我得到以下输出:
runhaskell test.hs
read_file.hs: Prelude.read: no parse
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮我理解我的代码有什么问题吗?谢谢.
您可能已经注意到,错误消息告诉您存在问题read,所以让我们关注它.
正如我在评论中所说,read采用某种数据类型的值的字符串表示,尝试解析它并返回该值.一些例子:
read "3.14" :: Double ? 3.14 :: Double
read "'a'" :: Char ? 'a' :: Char
read "[1,2,3]" :: [Int] ? [1,2,3] :: [Int]
Run Code Online (Sandbox Code Playgroud)
一些非例子:
read "[1,2," :: [Int] ? error "*** Exception: Prelude.read: no parse"
read "abc" :: Int ? error "*** Exception: Prelude.read: no parse"
Run Code Online (Sandbox Code Playgroud)
当你尝试使用(ie )String版本时会发生什么?readread :: String ? String
Haskell的表示String(例如,当您评估StringGHCi 中返回的内容时)由" ... "引号括起来的一系列字符组成.当然,如果你想显示一些特殊字符(比如换行符),你必须将转义版本放在那里(\n在这种情况下).
还记得我写的时候read需要一个值的字符串表示吗?在你的情况,read希望正是这个字符串格式.当然,它尝试做的第一件事就是匹配开头的报价.由于您的第一行没有开头",read抱怨并崩溃该程序.
read "hello" :: String以失败的方式read "1" :: [Int]失败; 1单独无法解析为Ints 列表- read期望字符串以开括号开头[.
您可能也听说过show,这是相反的(但非常松散)read.根据经验,如果您想要read一个值x,字符串表示形式应该是read这样的show x.
如果您要将文件的内容更改为以下内容
"this is line one"
"another line"
"and the final line"
Run Code Online (Sandbox Code Playgroud)
你的代码可以正常工作并产生以下输入:
["this is line one","another line","and the final line"]
Run Code Online (Sandbox Code Playgroud)
如果你不想改变你的.txt文件,只是删除list = listLines myLines和做print myLines.但是,当你运行程序时,你会得到
["this is line one","another line","and the final line"]
Run Code Online (Sandbox Code Playgroud)
再次.那么问题是什么?
print = putStrLn ? show并且show当它涉及show某些事物的列表时(即[a]对于某些事物a;除了Char获得特殊处理之外)的默认行为是产生字符串[ firstElement , secondElement ... lastElement ].如您所见,如果您想避开[ ... ],则必须将它们合并[String]在一起.
有一个漂亮的函数被调用unlines,这是相反的lines.另请注意,首先print调用show,但在这种情况下我们不希望这样(我们已经获得了我们想要的字符串)!所以我们使用putStrLn并完成了.最终版本:
main = do
handle <- openFile "data.txt" ReadMode
contents <- hGetContents handle
let myLines = lines contents
putStrLn (unlines myLines)
hClose handle
Run Code Online (Sandbox Code Playgroud)
我们也可以摆脱不必要的lines ~ unlines和公正的putStrLn contents.
| 归档时间: |
|
| 查看次数: |
230 次 |
| 最近记录: |