假设我有这样的数据结构:
create :: (boss -> [(action, boss)]) -- generator
-> boss
-> action
-> Person boss action
我想使用此功能从总统开始创建一个组织:
RMI
生成器创建员工列表。每个员工的老板都是当前调用该功能的人。我想为每个下属创建一个下属列表,依此类推(到无穷大)。
问题在于我不知道如何:
任何建议||参考非常感谢!
答案 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)