Haskell中如何修改Show与formatList函数生成指定Trip输出格式
修改Haskell中Show实例实现指定输出格式
原始代码
type Start = String type Destination = String type Distance = Float -- km type AverageSpeed = Float -- m/s type FirstClass = Bool data Trip = Trip Start [TravelOption] data TravelOption = Plane AverageSpeed Destination Distance FirstClass | Bus AverageSpeed Destination Distance | Train AverageSpeed Destination Distance FirstClass class VacationTrip a where instance Show TravelOption where show (Plane speed dest distance firstClass) = " by plane to " ++ dest show (Bus speed dest distance) = " by bus to " ++ dest show (Train speed dest distance firstClass) = "by train to " ++ dest instance Show Trip where show (Trip start travelOptions) = "[" ++ start ++ "]" ++ formatList (map show travelOptions) where formatList :: [String] -> String formatList [] = "" formatList [x] = "[" ++ x ++ "]" formatList (x:xs) = "(" ++ x ++ ") " ++ formatList xs
问题说明
当前代码生成的输出格式为:[Amsterdam] (by plane to Berlin) (by train to Paris) [by train to Cologne],但需要的输出格式为:[起点] by plane to (下一个城市) by train to (下一个城市) by train to [最后一个城市],要求每个中途城市用括号包裹,最后一个城市用方括号包裹。
修改方案
通过拆分交通描述与目的地的处理逻辑,调整Trip的Show实例实现需求格式:
type Start = String type Destination = String type Distance = Float -- km type AverageSpeed = Float -- m/s type FirstClass = Bool data Trip = Trip Start [TravelOption] data TravelOption = Plane AverageSpeed Destination Distance FirstClass | Bus AverageSpeed Destination Distance | Train AverageSpeed Destination Distance FirstClass class VacationTrip a where -- 提取交通方式的描述文本 getTravelDesc :: TravelOption -> String getTravelDesc (Plane _ _ _ _) = " by plane to" getTravelDesc (Bus _ _ _) = " by bus to" getTravelDesc (Train _ _ _ _) = " by train to" -- 提取旅行选项的目的地 getDestination :: TravelOption -> Destination getDestination (Plane _ dest _ _) = dest getDestination (Bus _ dest _) = dest getDestination (Train _ dest _ _) = dest instance Show Trip where -- 处理空行程的边界情况 show (Trip start []) = "[" ++ start ++ "]" show (Trip start opts) = "[" ++ start ++ "]" ++ concatMap (\(desc, dest) -> desc ++ " (" ++ dest ++ ")") initPairs ++ lastDesc ++ " [" ++ lastDest ++ "]" where -- 将所有旅行选项拆分为(交通描述, 目的地)的配对 allPairs = map (\opt -> (getTravelDesc opt, getDestination opt)) opts -- 取除最后一个外的所有配对 initPairs = init allPairs -- 提取最后一个选项的描述和目的地 (lastDesc, lastDest) = last allPairs
修改说明
- 新增
getTravelDesc和getDestination两个辅助函数,分别提取每个TravelOption的交通方式描述和目的地,让格式控制更灵活。 - 重构Trip的Show实例:
- 增加空行程的边界处理,避免列表操作报错。
- 将所有旅行选项转换为(交通描述, 目的地)的配对列表。
- 对中途的每个配对,拼接为
交通描述 (目的地)的格式。 - 最后一个配对单独处理为
交通描述 [目的地]的格式。 - 组合起点、中途部分和最后部分,生成符合要求的输出。
测试示例:
testTrip = Trip "Amsterdam" [Plane 250 "Berlin" 650 True, Train 150 "Paris" 800 False, Train 120 "Cologne" 500 True]
输出结果:[Amsterdam] by plane to (Berlin) by train to (Paris) by train to [Cologne]
内容的提问来源于stack exchange,提问作者Adnan Eren Güngörmüş
相关产品推荐
相关产品推荐

