使用 map/mapM 函数 return 准备好 putStrLn 分隔列表元素的字符串

Using the map/mapM function to return a String ready for putStrLn to separate list elements

我正在尝试创建以下类型的函数:

f1 :: [Car] -> String

其中 Car 是声明的类型,它是一个包含字符串、Int 和其他元组列表的元组。我想使用 map 函数来 return 一个字符串,该字符串将被传递到 main 函数,然后作为分隔的字符串输出。

无论如何,我有一个调用函数 f1 的主函数,如下所示:

putStrLn(f1 listOfCars)

listOfCars 的声明如您所料...

[("Ford", "Mondeo", 2009, [("Autotrader", 12000), ("Parkers", 11500)]), 

("VW", "Golf", 2011, [("Autotrader", 16000), ("Parkers", 15250)]),...]

我使用带有模式和守卫的递归函数以及 show 函数成功地做到了这一点,但同时研究了 mapmapM/mapM_ 函数我确信我可以以某种方式使用其中之一以更有效的方式执行此操作。我正在寻找有关如何使用这些功能之一的帮助。

您首先需要创建一个新函数,将单个汽车转换为可查看的字符串

carToString::Car->String
carToString car = <fill this in as you would like>

请注意,此函数比上面的 f1 更可重用!它可以用作构建块来处理存储在任何容器(树等)中的汽车。

一旦你有了这个,你就可以打印整个东西如下

putStrLn $ unlines $ map carToString listOfCars

或者,您可以使用 forM_(就是 flip mapM_),如下所示

forM_ listOfCars $ \car -> do
    putStrLn $ carToString car

或者如果您更喜欢简洁,

forM_ listOfCars $ putStrLn . carToString

请注意,可以修改第一种方法以给出 f1 的替代定义....

putStrLn $ unlines $ map carToString listOfCars

相同
putStrLn (unlines . map carToString $ listOfCars)

所以,f1可以定义为

f1 = unlines . map carToString

这是定义 f1 的一种非常简洁的方法。