[Haskell-cafe] Avoiding Dependency loops

martin martin.drautzburg at web.de
Sun Oct 25 10:35:02 UTC 2015

Thanks David.

Maybe I better show the actual code;

* module Process *

data Process r = Prc {
            prcSources  :: [Port],
            prcSinks    :: [Port],
            prcRunner   :: r,
            prcId       :: PrcId
} deriving (Show)

* module System *

data System = Sys {
            sysProcesses :: ProcessDb,
            sysItems     :: ItemDb
} deriving Show

type ProcessDb = M.Map Int (Process PrcRunner)

data PrcRunner = PrcRun (Timed Event -> Process PrcRunner -> State System EventQu)

I understand your reasoning about the type contraints, but I cannot see what I should actually do.

AS for your second suggestion of splitting things up even more, I don't think this will help, because the loop is
already on type level.

My feeling is that I got caught in OO thinking too much and the runner should not be part of the process at all. But
again I cannot see how to fix it. The thing is, Process itself does not really have any business with its Runner. There
is no function which actually does anyting with it. The Process type just provides a home for the runner.

Thinking aloud:

On top of the whole thing sits a simulation, which among others changes the state of the System. This includes changes
to the Processes. I want to capture this by altering the Runner associated with a particular Process. Wouldn't this
suggest that System needs an association between Process and Runner rather than making Runner a field of Process?

Am 10/25/2015 um 10:01 AM schrieb David Turner:
> Hi Martin,
> Seems reasonable to me. It's a common dependency-breaking technique, akin to introducing an interface in OO-land. Did
> you also introduce a typeclass constraint on the type 'r' so you can call some methods on it too? If not then Process
> doesn't really depend on System at all.
> Another thing to look for is that perhaps your System module splits into two bits, one low-level (defining types and so
> on) and one high-level (making use of everything in System and Process and Runner) and the two bits live at opposite
> ends of the dependency graph. I've found that quite a common situation to be in when splitting things up into modules too.
> HTH,
> David
> On 25 October 2015 at 08:36, martin <martin.drautzburg at web.de <mailto:martin.drautzburg at web.de>> wrote:
>     Hello all,
>     I just split up a program I'm working on into several source files and ran into the following difficulty:
>     module Process implements Process which has a field Runner. Runner is a basically a function which alters a 'System'
>     state. So Process needs Runner, Runner needs System and thus Process needs System.
>     module System implements among others a collection of Processes (because Processes can alter their states). So System
>     needs Process.
>     Eh voila, I have a loop.
>     What I did was to leave the type of the Runner unspecified in Process, i.e. I now have (Process r) where r is the type
>     of the Runner. Thus Process no longer needs to know about System.
>     This does work, but it feels strange and I'm a bit worried that this is an indication for a design flaw, but I cannot
>     see it.
>     _______________________________________________
>     Haskell-Cafe mailing list
>     Haskell-Cafe at haskell.org <mailto:Haskell-Cafe at haskell.org>
>     http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

More information about the Haskell-Cafe mailing list