Hi all,
I have a set of services, each one having zero or more dependencies on other services from the set. I would like to, given a list of services as input, to calculate the unique list of these services + their dependencies.
What I came up with so far is:
let Prelude = ./Prelude.dhall
let Service = < database | service1 | service2 >
let Service/equals =
let handlers = { database = False, service1 = False, service2 = False }
let isDatabase = \(s : Service) -> merge (handlers // { database = True}) s
let isService1 = \(s : Service) -> merge (handlers // { service1 = True}) s
let isService2 = \(s : Service) -> merge (handlers // { service2 = True}) s
let makeEquals =
\(predicates : List (Service -> Bool))
-> \(l : Service)
-> \(r : Service)
-> let apply = \(predicate : Service -> Bool) -> predicate l && predicate r
in
Prelude.Bool.or (
Prelude.List.map (Service -> Bool) Bool apply predicates
)
let equals = makeEquals [ isDatabase, isService1, isService2 ]
let example0 = assert : equals Service.database Service.service1 === False
let example1 = assert : equals Service.database Service.service2 === False
let example2 = assert : equals Service.service1 Service.service2 === False
let example3 = assert : equals Service.database Service.database === True
let example4 = assert : equals Service.service1 Service.service1 === True
let example5 = assert : equals Service.service2 Service.service2 === True
in equals
let uniqueServices =
\(ls : List Service)
-> let concatUnique =
\(s : Service)
-> \(rl : List Service)
-> if (Prelude.List.any Service (Service/equals s) rl)
then rl
else rl # [ s ]
in Prelude.List.fold
Service
ls
(List Service)
concatUnique
([] : List Service)
let services =
{ database.dependencies = [] : List Service
, service1.dependencies = [ Service.database ]
, service2.dependencies = [ Service.database, Service.service1 ]
}
let makeServiceList =
\(ls : List Service)
-> uniqueServices
(Prelude.List.concatMap
Service
Service
(\(s : Service) -> [ s ] # (merge services s).dependencies)
ls)
let example0 = assert : makeServiceList [ Service.database ] === [ Service.database ]
let example1 = assert : makeServiceList [ Service.service1 ] === [ Service.database, Service.service1 ]
let example2 = assert : makeServiceList [ Service.service2 ] ===
[ Service.service1, Service.database, Service.service2 ]
let example3 = assert : makeServiceList [ Service.service1, Service.service2 ] ===
[ Service.service1, Service.database, Service.service2 ]
let example4 = assert : makeServiceList [ Service.database, Service.service2 ] ===
[ Service.service1, Service.database, Service.service2 ]
in makeServiceList
(the equality implementation is based on Discussion: Text equality · Issue #164 · dhall-lang/dhall-lang · GitHub)
Note that I don’t need to resolve the dependency ordering, I just need to compute the unique list of services to output (and feed them to e.g., docker-compose
which will decide on the startup order).
This feels very inefficient (even though for the number Service
's in my use case it shouldn’t be an issue.)
Is this a sane thing to do? Is there a more elegant/efficient way to express this?
Thanks!