生成员工列表

时间:2017-04-28 07:07:35

标签: haskell

假设我有这样的数据结构:

create :: (boss -> [(action, boss)]) -- generator
       -> boss
       -> action
       -> Person boss action 

我想使用此功能从总统开始创建一个组织:

RMI

生成器创建员工列表。每个员工的老板都是当前调用该功能的人。我想为每个下属创建一个下属列表,依此类推(到无穷大)。

问题在于我不知道如何:

  • 将生成器生成的元素添加到当前节点的下属列表
  • 为每个下属递归(无限次)执行此操作。我想过某种地图,但我不明白。

任何建议||参考非常感谢!

2 个答案:

答案 0 :(得分:5)

这是一个比它看起来更难的问题。要了解原因,请考虑在调用boss时为create选择的类型。你说树中的每个分支都会创建以父节点为老板的下属。所以,显然boss不是该函数中的自由类型变量:它必须固定为Person。

但是你如何提供一个Person对象作为每个新人的老板?有一个循环引用,因为每个人在建设时都必须了解其上级以及所有下属。在你拥有所有下属之前,你不能创建首席执行官,但是在你拥有他们的老板之前不能创建这些。

现在,这实际上并不是不可能的:你可以通过懒惰的魔力在Haskell中创建没有变异的循环数据结构。但是这里没有理由,摩擦指出你的Person结构中的boss字段是无关紧要的。删除它,问题可能会简化到可以解决的问题。

听起来你仍然无法入门,所以我会提供一些改进的类型签名和你的功能可能看起来像什么的基本草图,并填写空白。

type Salary = Float
data Position job = Position {salary :: Salary,
                              job :: job
                             }

data Person job = Person { position :: Position job,
                           subordinates :: [Person job]
                         }

-- the job type our positions will be parameterized by
data Management = CEO | Executive | Manager

create :: (Position job -> [Position job])
       -> Position job
       -> Person job
create f root = Person root (hireSubordinates root)
  where hireSubordinates boss = _

testHiringPlan :: Position Management -> [Position Management]
testHiringPlan (Position salary job) = case job of
  CEO -> [Position _ Executive | subordinateNum <- _]
  Executive -> [Position _ Manager | subordinateNum <- _]
  Manager -> [Position _ Manager | subordinateNum <- _]

正如你所看到的,我已经把“这个人做了什么”(他们的立场)和“这个人管理的人”(他们的下属)的问题分开了。这样我们就可以从一个位置开始,然后通过为它们创建一个下属列表来生成实际的Person,避免任何循环引用。

我还提供了一个可能用于job类型变量的示例类型,这样我就可以生成一个传递给create的生成器的示例。

答案 1 :(得分:0)

在为问题提供的代码中,Person数据类型包含Person subordinates的列表,每个boss Person包含引用原始let字段的let字段1}}。循环参考。循环引用通常不必要地复杂化。

但是,如果您需要创建循环引用,可以在Person语句中完成

以下示例是您示例的精简版本。它保留了循环引用。在subordinates语句中,正在创建的subordinates是根据person定义的。生成器函数生成的data Action = Manager | TeamLeader | Programmer deriving Show data Person = Person { subordinates :: [Person] , act :: Action , boss :: Maybe Person } -- Generate the list of persons reporting to a boss generate :: Person -> [Person] generate boss = case act boss of -- A programmer has no subordinates Programmer -> [] -- Team leaders and managers have subordinates TeamLeader -> replicate 2 $ create generate (Just boss) Manager -> replicate 3 $ create generate (Just boss) -- Create a new person given that person's boss and a generator function -- that generates the person's subordinates create :: (Person -> [Person]) -> Maybe Person -> Person create generator maybeBoss = -- responsibility (action) depends on the boss's responsibility let action = case maybeBoss of Nothing -> Manager Just boss -> case act boss of Manager -> TeamLeader TeamLeader -> Programmer -- note the circular reference happening on the next lines subordinates = generator person person = Person subordinates action maybeBoss in person display :: Person -> IO () display (Person subordinates action boss ) = do putStrLn "" putStrLn $ "person: " ++ show action putStrLn $ "boss: " ++ show (fmap act boss) mapM_ display subordinates main = display $ create generate Nothing 是根据{% if user_rate %} <h2><a href="/games/{{game.id}}/{{game.slug}}/add_rate/edit/{{rate.id}}/">Edit rate</a></h2> {% else %} <h2><a href="/games/{{game.id}}/{{game.slug}}/add_rate">Add rate</a></h2> {% endif %} 定义的。

user_rate = Rate.objects.filter(user=request.user)