7

我如何告诉haskell,当show在代数类型的变量列表上调用时,应该在每行之后插入一个“\n”?

type Customer = (Int, Int, [Int])

我试图这样做:

instance of Show Customer where
show x = x ++ "\n"

但显然我只能为“数据......”之类的东西创建这样的实例。我该如何解决这个问题?

我只需要为客户列表派生Show,这样当我显示它时,输出很容易阅读,每行一个客户。

4

2 回答 2

10

要只显示在不同的行上,不要更改show,只需执行unlines (map show customerList). 这将显示它们中的每一个,然后将它们与中间的换行符重新组合在一起。


但是,您询问了将 show 更改为type同义词的问题,因此您可以选择:

show用于数据的基本序列化。如果你想做一些不同的事情,你有几个选择:

  1. 编写一个在这种情况下执行此操作的函数。
  2. display创建您自己的 Display 类并定义您喜欢如何在其功能中布置事物。
  3. 使用 anewtype包装数据。
  4. 声明您自己的客户类型。
  5. 稍后添加换行符

    类型客户 = (Int, Int, [Int])

示例 1

displayC :: Customer -> String
displayC = (++"\n").show

示例 2

{-# LANGUAGE TypeSynonymInstances,  FlexibleInstances #-}
class Display a where
  display :: a -> String

instance Display Customer where
   display x = show x ++ "\n"

(注意你应该说instance Display Customer而不是instance of Display Customer。)

示例输出:

*Main> display ((3,4,[5,6])::Customer)
"(3,4,[5,6])\n"

不过,应该谨慎使用这些语言扩展。

示例 3

newtype Cust = Cust Customer
displayCust (Cust c) = show c ++ "\n"

示例 4

data CustomerTup = CTup Int Int [Int]
displayCTup (CTup a b cs) = show (a,b,cs) ++ "\n"

甚至更好,

data CustomerRec = CRec {custno::Int, custAge::Int, custMeasurements::[Int]}
  deriving Show
displayCRec r = show (custno r,custAge r,custMeasurements r) ++ "\n"

你甚至可以坚持使用Show实例的做事方式。方法很好,data因为有更多的类型安全性,并且记录类型可以防止你犯一些微不足道的错误位置错误。

示例 5

stuff = unlines $ map show  [(1,2,[3,4]),(5,6,[7,8,9])]

甚至

morestuff = unlines [show (1,2,[3,4]), 
                     show (5,6,[7,8,9]),
                     "are all more numbery than",
                     show (True,4,False)]
于 2012-11-19T22:45:21.180 回答
3

对 AndrewC 的出色答案的一个小补充:

6.编写一个函数,为类中任何类型的文本表示添加新行Show

display :: Show a => a -> String
display = flip shows "\n"

例如:

> display (2, 3, [5, 7, 11])
"(2,3,[5,7,11])\n"
于 2012-11-20T01:07:32.573 回答