Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with circular dependencies in OCaml

Tags:

ocaml

I'm writing an interpreter for an experimental language. Three of the main constructs of the language are definitions, statements, and expressions. Definitions can contain statements and expressions, statements can contain definitions and expressions, and one kind of expression can contain statements. I represent all of these using union types so I can easily use pattern matching on them. Ideally, I would like to put the code for these in different files, but OMake complains about circular dependency issues. As far as I know, circular type definitions across modules are not allowed.

The only way I know of to solve this is to define all three types at once:

type defn = ...
and stmt = ...
and expr = ...

It seems like this requires all the code for types to be in the same file. Is there any way around this? How do you deal with circular definitions in your code?

like image 973
Jay Conrod Avatar asked Aug 30 '08 19:08

Jay Conrod


People also ask

How do you resolve circular dependency issues?

The best solution is to avoid circular dependencies, of course, but it you're truly stuck, you can work around the issue by using property injection and RegisterInstance<T>(T t) (or its equivalent, if you're not using Autofac).

How do I ignore circular dependency?

The Mediator Pattern can also help to lift circular dependencies by encapsulating the bidirectional interaction of two or more objects. The downside of your current code is (besides the circular dependency), that whenever class A changes and also data persistence changes, you have to touch and modify class B.

Is it okay to have circular dependency?

and, yes, cyclic dependencies are bad: They cause programs to include unnecessary functionality because things are dragged in which aren't needed. They make it a lot harder to test software. They make it a lot harder to reason about software.

How do you do a circular dependency?

Circular dependency problem can be overcome by using interfaces or events. So for the above problem, we can introduce an interface in between the “ MiddleTier ” and “ Dal ”. This interface project you will implement in the middle layer project on the “ Customer ” class.


2 Answers

Recursive definitions need to appear in the same file. If you want to separate definitions, statements, and expressions into separate modules, you can do so using recursive modules, but they will still need to appear in the same file. DAG-ifying inter-file dependencies is one of the annoyances of OCaml.

like image 106
Chris Conway Avatar answered Sep 29 '22 16:09

Chris Conway


This is easily solved by parameterizing your types over the types they refer to:

type ('stmt, 'expr) defn = ...
type ('defn, 'expr) stmt = ...
type ('defn, 'stmt) expr = ...

This technique is called "untying the recursive knot" (in reference to Gordian's knot) and was described in an OCaml Journal article.

Cheers, Jon Harrop.

like image 23
J D Avatar answered Sep 29 '22 14:09

J D