键入Car =(String,[String],Int,[String])
carToString :: [Car] -> IO()
carToString [] = putStr ""
carToString (x:xs) = putStr x ++ "\n" : putStr xs ++ "\n"
displayAllCars :: IO ()
displayAllCars = putStr carToString testDatabase --< test data in the format of type Car
这给了我错误:
ERROR file:.\template.hs:26 - Type error in application
*** Expression : putStr xs
*** Term : xs
*** Type : [([Char],[[Char]],Int,[[Char]])]
*** Does not match : [Char]
此错误的原因是什么?如何更正?
答案 0 :(得分:3)
尝试改为
displayAllCars :: [Car] -> IO ()
displayAllCars = mapM_ (putStrLn . show)
自然会推广到像
这样的东西putStrLnAll :: Show a => [a] -> IO ()
putStrLnAll = mapM_ (putStrLn . show)
我认为这可以满足您的需求。您的代码几乎无法解读,因为函数的名称与实际名称不符。
迭代汽车的一个例子:
iter [] = ?
iter x@(v1, v2, v3, v4):xs = do stuff with x (the car) and its values v1, v2, v3, v4 then call iter xs.
要将它们全部折叠成一个字符串,您可能需要类似的东西(假设存在displayCar :: Car -> String
)。我再次避免使用显式递归,转而使用辅助函数。
displayAllCars = foldl' (\acc val -> acc ++ "\n" ++ val) []
但是,我们可以使用递归:(通常的警告适用于任何非尾部优化的递归函数。如果列表很大,你将获得堆栈溢出。使用foldl'生产代码中的版本。如果可以接受后退列表,则折叠是最好的。
displayAllCars [] = []
displayAllCars c:cs = displayCar c ++ "\n" ++ displayCar cs
答案 1 :(得分:2)
当你写:
putStr x ++ "\n"
这将被解析如下:
(putStr x) ++ "\n"
这可能不是你想要的。尝试
putStr ( x ++ "\n" )
另请注意:运算符的类型为a - &gt; [a] - &gt; [a],即第二个操作数必须是一个列表。但是你有同样的东西: 这将解释异乎寻常的错误消息,因为它会导致编译器将已经错误的类型与其列表形式匹配.....
答案 2 :(得分:1)
除其他事项之外,似乎尚未指出的一个问题是,您尝试将putStr
(期望[Char]
)应用于carToString
(即使在给定参数之后,返回IO ()
)的函数。由于carToString
已经使用putStr
,只需摆脱putStr
中的displayAllCars
。
答案 3 :(得分:0)
试试这个:
carToString :: [Car] -> [IO()]
carToString [] = [putStr ""]
carToString (x:xs) = putStr x ++ "\n" : carToString xs ++ "\n"
你不需要显示所有车辆。您只需调用carToString函数并传递Car
列表即可