假设我们有
data D = X Int | Y Int Int | Z String
我希望能有一个名为getDConst
的函数。
getDConst :: D -> String
根据输入的数据构造函数,返回“X”、“Y”或“Z”之一。有没有通用的方法可以在不必为每个数据构造函数都进行case
的情况下编写此代码?(我可以接受依赖于 Data.Typeable
或类似东西的解决方案)
假设我们有
data D = X Int | Y Int Int | Z String
我希望能有一个名为getDConst
的函数。
getDConst :: D -> String
根据输入的数据构造函数,返回“X”、“Y”或“Z”之一。有没有通用的方法可以在不必为每个数据构造函数都进行case
的情况下编写此代码?(我可以接受依赖于 Data.Typeable
或类似东西的解决方案)
我自己找到了解决方案,但是留下这个问题来帮助其他人:
import Data.Data
data D = X Int | Y Int Int deriving (Data,Typeable)
let result = show $ toConstr (X 3) -- result contains what we wanted
如果您不想使用Typeable
,也可以使用Show
来实现此操作。
getDConst :: D -> String
getDConst = head . words . show
Show
不会输出所有的字段,因为它是惰性的。你可以在 ghci
中运行以下代码进行测试:
Prelude> data D = D [Int] deriving (Show)
Prelude> getDConst $ D [1..]
"D"
show
是惰性求值的,所以这可能不会很慢。注意 take 5 (show (Just undefined))
能够正常工作。 - Ben MillwoodtakeWhile (/=' ') . show
的代码)。 - Lynn我对这个问题有一个非常基本的答案,不需要进行导入或其他操作。它只是一个简单的函数。
假设我有以下数据。数据定义中重复的 Int 是有意为之的,因为我之后会使用“不关心”符号:
data YES_NO_CANCEL = YES Int | NO Int Int | CANCEL Int Int Int
那么你可以创建一个函数:
extractDataType :: YES_NO_CANCEL -> String
extractDataType (YES _) = "YES"
extractDataType (NO _ _) = "NO"
extractDataType (CANCEL _ _ _) = "CANCEL"
{-# LANGUAGE DeriveDataTypeable #-}
。在 GHC 中,当您派生 Data 和 Typeable 时,这是必需的。 - jplatteshowConstr
而不是show
。它们的功能完全相同,但showConstr
使用错误类型的风险较小。 - undefined