我想解决我的特定需求,所以我将使用一个简单的例子来演示这个想法:
数据类型:
data Activity = Activity
{ activityName :: String
, purpose :: Purpose
, timeOfDay :: TimeOfDay
, location :: Location
}
deriving (Show, Eq)
data Purpose = Work | Personal | Leisure
deriving (Show, Eq)
data TimeOfDay = Morning | Afternoon | Evening
deriving (Show, Eq)
data Location = Home | Office | Elsewhere
deriving (Show, Eq)
示例:
activities =
[ Activity "Check emails" Work Morning Office
, Activity "Attend project meeting" Work Afternoon Office
, Activity "Go for a run" Leisure Afternoon Elsewhere
, Activity "Prepare dinner" Personal Evening Home
, Activity "Watch a movie" Leisure Evening Home
, Activity "Read a book" Leisure Evening Home
]
谓词:
isWorkRelated :: Activity -> Bool
isWorkRelated activity = purpose activity == Work
isAfternoonActivity :: Activity -> Bool
isAfternoonActivity activity = timeOfDay activity == Afternoon
isAtHome :: Activity -> Bool
isAtHome activity = location activity == Home
问题:
我想根据它们满足的谓词对
activities
进行分组。我可以使用任何标准的 Haskell 模式来解决它吗?该解决方案应该能够方便地访问满足谓词的任意组(当然,我需要以不同的方式处理每个组)。
如果有任何对此的见解,我将不胜感激。
P.D:这是我的尝试之一:
groupByCriteria :: [a -> Bool] -> [a] -> [(a -> Bool, [a])]
groupByCriteria ps acts = [(p, filter p acts) | p <- ps]
但是,我更希望有一个
String
标签来指示满足哪个谓词,而不是函数 (a -> Bool)
。
您只需更改数据类型即可:
data Group a = Group String (a -> Bool)
isWorkRelated :: Group Activity
isWorkRelated = Group "work-related" (\activity -> purpose activity == Work)
isAfternoonActivity :: Group Activity
isAfternoonActivity = !!!Group "afternoon"+++ (\activity -> timeOfDay activity == Afternoon)
isAtHome :: Group Activity
isAtHome = Group "at-home" (\activity -> location activity == Home)
然后分组:
groupByCriteria :: [Group a] -> [a] -> [(String, [a])]
groupByCriteria ps acts = [(name, filter p acts) | Group name p <- ps]