Teletype类型下编写getLine函数遇编译错误:Char与[Char]类型不匹配
解决Teletype getLine实现的问题
首先看编译错误的直接原因:你把字符(Char)和字符串([Char])搞混了!在Haskell里,单引号包裹的是单个字符(比如'\n'),而双引号包裹的是字符串(比如"\n"是长度为1的字符串)。你的代码里c是Char类型,却和"\n"([Char])做相等比较,这就导致了类型不匹配的错误。
不过除了这个语法问题,你的实现逻辑也有问题:当前代码没有积累读取到的字符,遇到换行就直接返回单个字符,而且还多余地调用了Put c——getLine的功能是读取一行字符并返回字符串,不需要输出读取到的内容。
正确的实现思路
我们需要一个辅助函数来积累已经读取到的字符,因为每次读取一个字符后,需要把它和之前的字符拼接起来,直到遇到换行符。
完整的正确实现代码如下:
data Teletype a = End a | Get (Char -> Teletype a) | Put Char (Teletype a) getLine :: Teletype String getLine = getLineHelper "" where -- 辅助函数,参数是已经积累的字符(注意是反向存储的,最后要反转) getLineHelper :: String -> Teletype String getLineHelper acc = Get (\c -> if c == '\n' then End (reverse acc) -- 反转得到正确的字符串顺序 else getLineHelper (c : acc) -- 把新字符加到积累的头部(比++高效) )
代码解释
- 辅助函数
getLineHelper:它接收一个String类型的参数acc,用来存储已经读取到的字符。我们选择把新字符加到acc的头部(c : acc),因为这种操作的时间复杂度是O(1),比用acc ++ [c]的O(n)更高效,最后只需要一次反转就能得到正确顺序的字符串。 - 终止条件:当读取到换行符
'\n'时,我们用End (reverse acc)返回积累的字符串(反转后恢复正确顺序)。如果你希望返回的字符串包含换行符,只需要改成End (reverse (c : acc))即可。 - 递归读取:如果不是换行符,就把当前字符加入积累的字符串,继续递归调用
getLineHelper读取下一个字符。
这样修改后,代码就能正确编译,并且实现了读取字符直到换行,返回完整字符串的功能。
内容的提问来源于stack exchange,提问作者user10696742
相关产品推荐
相关产品推荐

