使用 `show` 而不是整个显示字符串时如何访问数据类型的字段?
How can I access the fields of a data type when using `show` instead of the whole show string?
我是命令式编程出身,正在学习Haskell。我有以下数据类型:
newtype Prename = Prename String deriving (Show)
newtype Surname = Surname String deriving (Show)
data Employment = Employed | Unemployed
data Person = P Prename Surname Employment
jondoe = P (Prename "John") (Surname "Doe") Employed
如何在没有构造函数的情况下访问 Prename
和 Surname
的字符串。目前我得到以下输出:
show jondoe
"P (Prename\"John\") (Surname\"Doe\") (Employed)"
但我希望它是
show jondoe
"John Doe"
我感到非常沮丧,因为这似乎是一件很简单的事情,我该如何实现呢?
有几种方法可以做到这一点。一种方法是编写一个将名称写入终端的函数,如下所示:
writeName :: Person -> IO ()
writeName (P (Prename p) (Surname s) _) = putStrLn (p ++ " " ++ s)
λ> writeName jondoe
John Doe
另一种方法是 returns 连接全名作为字符串的函数:
getFullname :: Person -> String
getFullname (P (Prename p) (Surname s) _) = p ++ " " ++ s
getFullname :: Person -> String
getFullname (P (Prename p) (Surname s) _) = p ++ " " ++ s
第三种方法是为 Person
实现 Show
的实例,如下所示:
instance Show Person where
show (P (Prename p) (Surname s) _) = p ++ " " ++ s
λ> show jondoe
"John Doe"
但老实说,我不确定以这种方式实现 Show
实例是否是个好主意,因为您丢失了 Employment
信息。拥有一个明确说明其功能的自定义函数对我来说似乎是更好的方法。
show
是 而不是 以获得漂亮的输出。它专门用于生成 有效 Haskell 代码 。现在,"John Doe"
在语法上当然是有效的,但它没有正确的类型。
也就是说,我个人认为将 Show
实例基于自定义智能构造函数是完全可以的,这将使它更具可读性。例如,您可以
employee :: Prename -> Surname -> Person
employee pn sn = P pn sn Employed
nonworker :: Prename -> Surname -> Person
nonworker pn sn = P pn sn Unemployed
此外,您可能会问自己 Prename
和 Surname
是否真的需要 newtypes
。如果你只是简单地制作它们
type Prename = String
type Surname = String
然后它们可以直接打印为...好吧,字符串。现在你可以写一个 Show
实例
instance Show Person where
showsPrec p (P pn sn Employed)
= showParen (p>9)
$ ("employee "++)
. showsPrec 11 pn
. showsPrec 11 sn
showsPrec p (P pn sn Unemployed)
= ...
我是命令式编程出身,正在学习Haskell。我有以下数据类型:
newtype Prename = Prename String deriving (Show)
newtype Surname = Surname String deriving (Show)
data Employment = Employed | Unemployed
data Person = P Prename Surname Employment
jondoe = P (Prename "John") (Surname "Doe") Employed
如何在没有构造函数的情况下访问 Prename
和 Surname
的字符串。目前我得到以下输出:
show jondoe
"P (Prename\"John\") (Surname\"Doe\") (Employed)"
但我希望它是
show jondoe
"John Doe"
我感到非常沮丧,因为这似乎是一件很简单的事情,我该如何实现呢?
有几种方法可以做到这一点。一种方法是编写一个将名称写入终端的函数,如下所示:
writeName :: Person -> IO ()
writeName (P (Prename p) (Surname s) _) = putStrLn (p ++ " " ++ s)
λ> writeName jondoe
John Doe
另一种方法是 returns 连接全名作为字符串的函数:
getFullname :: Person -> String
getFullname (P (Prename p) (Surname s) _) = p ++ " " ++ s
getFullname :: Person -> String
getFullname (P (Prename p) (Surname s) _) = p ++ " " ++ s
第三种方法是为 Person
实现 Show
的实例,如下所示:
instance Show Person where
show (P (Prename p) (Surname s) _) = p ++ " " ++ s
λ> show jondoe
"John Doe"
但老实说,我不确定以这种方式实现 Show
实例是否是个好主意,因为您丢失了 Employment
信息。拥有一个明确说明其功能的自定义函数对我来说似乎是更好的方法。
show
是 而不是 以获得漂亮的输出。它专门用于生成 有效 Haskell 代码 。现在,"John Doe"
在语法上当然是有效的,但它没有正确的类型。
也就是说,我个人认为将 Show
实例基于自定义智能构造函数是完全可以的,这将使它更具可读性。例如,您可以
employee :: Prename -> Surname -> Person
employee pn sn = P pn sn Employed
nonworker :: Prename -> Surname -> Person
nonworker pn sn = P pn sn Unemployed
此外,您可能会问自己 Prename
和 Surname
是否真的需要 newtypes
。如果你只是简单地制作它们
type Prename = String
type Surname = String
然后它们可以直接打印为...好吧,字符串。现在你可以写一个 Show
实例
instance Show Person where
showsPrec p (P pn sn Employed)
= showParen (p>9)
$ ("employee "++)
. showsPrec 11 pn
. showsPrec 11 sn
showsPrec p (P pn sn Unemployed)
= ...