假设我们用以下方式表示公司层次结构:
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Data
import Data.Generics.Aliases
import Data.Generics.Schemes
data CompanyAsset = Employee Name Salary
| Plant Name
| Boss Name Performance Salary [CompanyAsset]
| Pet Name
| Car Id
| Guild [CompanyAsset]
| Fork CompanyAsset CompanyAsset
-- ... and imagine 100 more options that recursively use `CompanyAsset`.
deriving (Show, Data)
-- Performance of the department.
data Performance = Good | Bad deriving (Show, Data)
type Name = String
type Id = Int
newtype Salary = Salary Double deriving (Show, Data, Typeable)
raise :: Salary -> Salary
我想定义一个功能,它可以提高公司资产的工资,这些资产没有Boss
祖先的部门有Bad
业绩。这样的函数可以很容易地定义如下:
raiseSalaries :: CompanyAsset -> CompanyAsset
raiseSalaries (Boss n Good s as) = Boss n Good (raise s) (raiseSalaries <$> as)
raiseSalaries a@(Boss _ Bad _ _) = a -- The salaries of everything below are not raised if the performance is 'Bad'
raiseSalaries ... -- and from here onwards we have **boilerplate**!
问题是这需要很多样板文件(为了讨论,请假设CompanyAsset
已给出且无法更改)。
所以我的问题是是否有一种遍历数据结构的方法可以避免上面的样板。
这个问题与我发布的一个类似问题有关,但在这种情况下使用everywhere'
不会有帮助,因为在某些情况下不应该提高工资。