├── LICENSE ├── README.md ├── package.dhall ├── render.dhall ├── schemas.dhall └── types.dhall /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Gabriella Gonzalez 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the author nor the names of its contributors may be 15 | used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `dhall-dot` 2 | 3 | This package provides [Dhall](https://dhall-lang.org/) support for the 4 | [DOT language](https://graphviz.org/doc/info/lang.html) used by the 5 | [Graphviz](https://graphviz.org/about/) package. This support consists of: 6 | 7 | * [GraphViz types](./types.dhall) encoded in Dhall 8 | * A [`render`](./render.dhall) function to render a `Graph` as `Text` 9 | 10 | See the [`package.dhall`](./package.dhall) file for example usage. 11 | -------------------------------------------------------------------------------- /package.dhall: -------------------------------------------------------------------------------- 1 | let types = ./types.dhall 2 | 3 | let schemas = ./schemas.dhall 4 | 5 | let render = ./render.dhall 6 | 7 | let dhall-dot = types ⫽ schemas ⫽ { render } 8 | 9 | let minimalExample = 10 | assert 11 | : dhall-dot.render 12 | { strict = False 13 | , directionality = dhall-dot.Directionality.graph 14 | , id = None dhall-dot.ID 15 | , statements = [] : List dhall-dot.Statement 16 | } 17 | ≡ '' 18 | graph { } 19 | '' 20 | 21 | let maximalExample = 22 | assert 23 | : dhall-dot.render 24 | { strict = True 25 | , directionality = dhall-dot.Directionality.digraph 26 | , id = Some "A" 27 | , statements = 28 | [ dhall-dot.statement.node 29 | { nodeID = 30 | { id = "Node #0" 31 | , port = Some 32 | (dhall-dot.Port.CompassPoint dhall-dot.CompassPoint.n) 33 | } 34 | , attributes = toMap { color = "red" } 35 | } 36 | , dhall-dot.statement.node 37 | { nodeID = { id = "Node #1", port = None dhall-dot.Port } 38 | , attributes = [] : List dhall-dot.Attribute 39 | } 40 | , dhall-dot.statement.edges 41 | { vertices = 42 | [ dhall-dot.vertex.nodeID 43 | { id = "Node #0" 44 | , port = Some 45 | ( dhall-dot.Port.CompassPoint 46 | dhall-dot.CompassPoint.n 47 | ) 48 | } 49 | , dhall-dot.vertex.nodeID 50 | { id = "Node #1", port = None dhall-dot.Port } 51 | , dhall-dot.vertex.subgraph 52 | ( dhall-dot.subgraph 53 | { id = Some "cluster_0" 54 | , attributes = toMap { style = "filled" } 55 | , statements = 56 | [ dhall-dot.statement.node 57 | { nodeID = 58 | { id = "Subgraph #0 - Node #0" 59 | , port = None dhall-dot.Port 60 | } 61 | , attributes = [] : List dhall-dot.Attribute 62 | } 63 | , dhall-dot.statement.node 64 | { nodeID = 65 | { id = "Subgraph #0 - Node #1" 66 | , port = None dhall-dot.Port 67 | } 68 | , attributes = [] : List dhall-dot.Attribute 69 | } 70 | ] 71 | } 72 | ) 73 | ] 74 | , attributes = toMap { label = "Label #0" } 75 | } 76 | , dhall-dot.statement.subgraph 77 | ( dhall-dot.subgraph 78 | { id = Some "Subgraph #1" 79 | , attributes = [] : List dhall-dot.Attribute 80 | , statements = 81 | [ dhall-dot.statement.node 82 | { nodeID = 83 | { id = "Subgraph #1 - Node #0" 84 | , port = None dhall-dot.Port 85 | } 86 | , attributes = [] : List dhall-dot.Attribute 87 | } 88 | , dhall-dot.statement.node 89 | { nodeID = 90 | { id = "Subgraph #1 - Node #1" 91 | , port = None dhall-dot.Port 92 | } 93 | , attributes = [] : List dhall-dot.Attribute 94 | } 95 | ] 96 | } 97 | ) 98 | ] 99 | } 100 | ≡ '' 101 | strict digraph "A" { "Node #0":n [ "color" = "red" ]; "Node #1"; "Node #0":n -> "Node #1" -> subgraph "cluster_0" { "style" = "filled"; "Subgraph #0 - Node #0"; "Subgraph #0 - Node #1"; } [ "label" = "Label #0" ]; subgraph "Subgraph #1" { "Subgraph #1 - Node #0"; "Subgraph #1 - Node #1"; }; } 102 | '' 103 | 104 | in dhall-dot 105 | -------------------------------------------------------------------------------- /render.dhall: -------------------------------------------------------------------------------- 1 | let Text/concatSep = 2 | https://prelude.dhall-lang.org/v17.1.0/Text/concatSep.dhall sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58 3 | 4 | let Text/concatMapSep = 5 | https://prelude.dhall-lang.org/v17.1.0/Text/concatMapSep.dhall sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840 6 | 7 | let List/map = 8 | https://prelude.dhall-lang.org/v17.1.0/List/map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 9 | 10 | let List/null = 11 | https://prelude.dhall-lang.org/v17.1.0/List/null.dhall sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80 12 | 13 | let types = ./types.dhall 14 | 15 | let compassPoint = 16 | λ(c : types.CompassPoint) → 17 | merge 18 | { n = "n" 19 | , ne = "ne" 20 | , e = "e" 21 | , se = "se" 22 | , s = "s" 23 | , sw = "sw" 24 | , w = "w" 25 | , nw = "nw" 26 | , c = "c" 27 | , _ = "_" 28 | } 29 | c 30 | 31 | let id = Text/show 32 | 33 | let directionality = 34 | λ(d : types.Directionality) → 35 | merge { graph = "graph", digraph = "digraph" } d 36 | 37 | let port = 38 | λ(p : types.Port) → 39 | merge 40 | { CompassPoint = λ(c : types.CompassPoint) → ":${compassPoint c}" 41 | , ID = λ(i : types.ID) → ":${id i}" 42 | , Both = 43 | λ(b : { id : types.ID, compassPoint : types.CompassPoint }) → 44 | ":${id b.id}:${compassPoint b.compassPoint}" 45 | } 46 | p 47 | 48 | let attribute = λ(a : types.Attribute) → "${id a.mapKey} = ${id a.mapValue}" 49 | 50 | let attributeList = 51 | λ(`as` : List types.Attribute) → 52 | "[ ${Text/concatMapSep ", " types.Attribute attribute `as`} ]" 53 | 54 | let graphAttributeList = 55 | λ(`as` : List types.Attribute) → 56 | "${Text/concatMapSep "; " types.Attribute attribute `as`};" 57 | 58 | let attributeType = 59 | λ(t : types.AttributeType) → 60 | merge { graph = "graph", node = "node", edge = "edge" } t 61 | 62 | let edge = 63 | λ(d : types.Directionality) → merge { graph = " -- ", digraph = " -> " } d 64 | 65 | let nodeID = 66 | λ(n : types.NodeID) → 67 | let renderedPort = merge { None = "", Some = port } n.port 68 | 69 | in "${id n.id}${renderedPort}" 70 | 71 | let statement = 72 | λ(d : types.Directionality) → 73 | λ(s : types.Statement) → 74 | s 75 | { Statement = Text, Vertex = Text, SubGraph = Text } 76 | { statement = 77 | { node = 78 | λ ( x 79 | : { nodeID : { id : types.ID, port : Optional types.Port } 80 | , attributes : List types.Attribute 81 | } 82 | ) → 83 | let renderedAttributeList = 84 | if List/null types.Attribute x.attributes 85 | then [] : List Text 86 | else [ attributeList x.attributes ] 87 | 88 | in Text/concatSep 89 | " " 90 | ([ nodeID x.nodeID ] # renderedAttributeList) 91 | , edges = 92 | λ ( x 93 | : { vertices : List Text, attributes : List types.Attribute } 94 | ) → 95 | let renderedAttributeList = 96 | if List/null types.Attribute x.attributes 97 | then [] : List Text 98 | else [ attributeList x.attributes ] 99 | 100 | in Text/concatSep 101 | " " 102 | ( [ Text/concatSep (edge d) x.vertices ] 103 | # renderedAttributeList 104 | ) 105 | , attributes = 106 | λ ( x 107 | : { type : types.AttributeType 108 | , attributes : List types.Attribute 109 | } 110 | ) → 111 | "${attributeType x.type} ${attributeList x.attributes}" 112 | , attribute 113 | , subgraph = λ(x : Text) → x 114 | } 115 | , vertex = { nodeID, subgraph = λ(x : Text) → x } 116 | , subgraph = 117 | λ ( x 118 | : { id : Optional Text 119 | , attributes : List types.Attribute 120 | , statements : List Text 121 | } 122 | ) → 123 | let renderedID = 124 | merge 125 | { None = [] : List Text 126 | , Some = λ(i : types.ID) → [ "subgraph", id i ] 127 | } 128 | x.id 129 | 130 | let renderedAttributeList = 131 | if List/null types.Attribute x.attributes 132 | then [] : List Text 133 | else [ graphAttributeList x.attributes ] 134 | 135 | in Text/concatSep 136 | " " 137 | ( renderedID 138 | # [ "{" ] 139 | # renderedAttributeList 140 | # List/map 141 | Text 142 | Text 143 | (λ(t : Text) → "${t};") 144 | x.statements 145 | # [ "}" ] 146 | ) 147 | } 148 | 149 | let graph 150 | : types.Graph → Text 151 | = λ(g : types.Graph) → 152 | let renderedStrict = if g.strict then [ "strict" ] else [] : List Text 153 | 154 | let renderedID = 155 | merge 156 | { None = [] : List Text, Some = λ(i : types.ID) → [ id i ] } 157 | g.id 158 | 159 | let renderedStatements = 160 | List/map 161 | types.Statement 162 | Text 163 | (λ(s : types.Statement) → "${statement g.directionality s};") 164 | g.statements 165 | 166 | in Text/concatSep 167 | " " 168 | ( renderedStrict 169 | # [ directionality g.directionality ] 170 | # renderedID 171 | # [ "{" ] 172 | # renderedStatements 173 | # [ "}" ] 174 | ) 175 | ++ "\n" 176 | 177 | in graph 178 | -------------------------------------------------------------------------------- /schemas.dhall: -------------------------------------------------------------------------------- 1 | let types = ./types.dhall 2 | 3 | let NodeID = { Type = types.NodeID, default.port = None types.Port } 4 | 5 | let Graph = 6 | { Type = types.Graph 7 | , default = 8 | { strict = False 9 | , id = None types.ID 10 | , statements = [] : List types.Statement 11 | } 12 | } 13 | 14 | in { NodeID, Graph } 15 | -------------------------------------------------------------------------------- /types.dhall: -------------------------------------------------------------------------------- 1 | let List/map = 2 | https://prelude.dhall-lang.org/v17.1.0/List/map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 3 | 4 | let ID = Text 5 | 6 | let CompassPoint = < _ | c | e | n | ne | nw | s | se | sw | w > 7 | 8 | let Port = 9 | < ID : ID 10 | | CompassPoint : CompassPoint 11 | | Both : { id : ID, compassPoint : CompassPoint } 12 | > 13 | 14 | let Attribute = { mapKey : ID, mapValue : ID } 15 | 16 | let AttributeType = < edge | graph | node > 17 | 18 | let NodeID = { id : ID, port : Optional Port } 19 | 20 | let Statement = 21 | ∀(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 22 | ∀ ( constructors 23 | : { statement : 24 | { node : 25 | { nodeID : NodeID, attributes : List Attribute } → 26 | types.Statement 27 | , edges : 28 | { vertices : List types.Vertex 29 | , attributes : List Attribute 30 | } → 31 | types.Statement 32 | , attributes : 33 | { type : AttributeType, attributes : List Attribute } → 34 | types.Statement 35 | , attribute : Attribute → types.Statement 36 | , subgraph : types.SubGraph → types.Statement 37 | } 38 | , vertex : 39 | { nodeID : NodeID → types.Vertex 40 | , subgraph : types.SubGraph → types.Vertex 41 | } 42 | , subgraph : 43 | { id : Optional Text 44 | , attributes : List Attribute 45 | , statements : List types.Statement 46 | } → 47 | types.SubGraph 48 | } 49 | ) → 50 | types.Statement 51 | 52 | let Vertex = 53 | ∀(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 54 | ∀ ( constructors 55 | : { statement : 56 | { node : 57 | { nodeID : NodeID, attributes : List Attribute } → 58 | types.Statement 59 | , edges : 60 | { vertices : List types.Vertex 61 | , attributes : List Attribute 62 | } → 63 | types.Statement 64 | , attributes : 65 | { type : AttributeType, attributes : List Attribute } → 66 | types.Statement 67 | , attribute : Attribute → types.Statement 68 | , subgraph : types.SubGraph → types.Statement 69 | } 70 | , vertex : 71 | { nodeID : NodeID → types.Vertex 72 | , subgraph : types.SubGraph → types.Vertex 73 | } 74 | , subgraph : 75 | { id : Optional Text 76 | , attributes : List Attribute 77 | , statements : List types.Statement 78 | } → 79 | types.SubGraph 80 | } 81 | ) → 82 | types.Vertex 83 | 84 | let SubGraph = 85 | ∀(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 86 | ∀ ( constructors 87 | : { statement : 88 | { node : 89 | { nodeID : NodeID, attributes : List Attribute } → 90 | types.Statement 91 | , edges : 92 | { vertices : List types.Vertex 93 | , attributes : List Attribute 94 | } → 95 | types.Statement 96 | , attributes : 97 | { type : AttributeType, attributes : List Attribute } → 98 | types.Statement 99 | , attribute : Attribute → types.Statement 100 | , subgraph : types.SubGraph → types.Statement 101 | } 102 | , vertex : 103 | { nodeID : NodeID → types.Vertex 104 | , subgraph : types.SubGraph → types.Vertex 105 | } 106 | , subgraph : 107 | { id : Optional Text 108 | , attributes : List Attribute 109 | , statements : List types.Statement 110 | } → 111 | types.SubGraph 112 | } 113 | ) → 114 | types.SubGraph 115 | 116 | let statement 117 | : { node : { nodeID : NodeID, attributes : List Attribute } → Statement 118 | , edges : 119 | { vertices : List Vertex, attributes : List Attribute } → Statement 120 | , attributes : 121 | { type : AttributeType, attributes : List Attribute } → Statement 122 | , attribute : Attribute → Statement 123 | , subgraph : SubGraph → Statement 124 | } 125 | = { node = 126 | λ(x : { nodeID : NodeID, attributes : List Attribute }) → 127 | λ(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 128 | λ ( constructors 129 | : { statement : 130 | { node : 131 | { nodeID : NodeID, attributes : List Attribute } → 132 | types.Statement 133 | , edges : 134 | { vertices : List types.Vertex 135 | , attributes : List Attribute 136 | } → 137 | types.Statement 138 | , attributes : 139 | { type : AttributeType, attributes : List Attribute } → 140 | types.Statement 141 | , attribute : Attribute → types.Statement 142 | , subgraph : types.SubGraph → types.Statement 143 | } 144 | , vertex : 145 | { nodeID : NodeID → types.Vertex 146 | , subgraph : types.SubGraph → types.Vertex 147 | } 148 | , subgraph : 149 | { id : Optional Text 150 | , attributes : List Attribute 151 | , statements : List types.Statement 152 | } → 153 | types.SubGraph 154 | } 155 | ) → 156 | constructors.statement.node x 157 | , edges = 158 | λ(x : { vertices : List Vertex, attributes : List Attribute }) → 159 | λ(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 160 | λ ( constructors 161 | : { statement : 162 | { node : 163 | { nodeID : NodeID, attributes : List Attribute } → 164 | types.Statement 165 | , edges : 166 | { vertices : List types.Vertex 167 | , attributes : List Attribute 168 | } → 169 | types.Statement 170 | , attributes : 171 | { type : AttributeType, attributes : List Attribute } → 172 | types.Statement 173 | , attribute : Attribute → types.Statement 174 | , subgraph : types.SubGraph → types.Statement 175 | } 176 | , vertex : 177 | { nodeID : NodeID → types.Vertex 178 | , subgraph : types.SubGraph → types.Vertex 179 | } 180 | , subgraph : 181 | { id : Optional Text 182 | , attributes : List Attribute 183 | , statements : List types.Statement 184 | } → 185 | types.SubGraph 186 | } 187 | ) → 188 | constructors.statement.edges 189 | { vertices = 190 | let adapt = λ(v : Vertex) → v types constructors 191 | 192 | in List/map Vertex types.Vertex adapt x.vertices 193 | , attributes = x.attributes 194 | } 195 | , attributes = 196 | λ(x : { type : AttributeType, attributes : List Attribute }) → 197 | λ(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 198 | λ ( constructors 199 | : { statement : 200 | { node : 201 | { nodeID : NodeID, attributes : List Attribute } → 202 | types.Statement 203 | , edges : 204 | { vertices : List types.Vertex 205 | , attributes : List Attribute 206 | } → 207 | types.Statement 208 | , attributes : 209 | { type : AttributeType, attributes : List Attribute } → 210 | types.Statement 211 | , attribute : Attribute → types.Statement 212 | , subgraph : types.SubGraph → types.Statement 213 | } 214 | , vertex : 215 | { nodeID : NodeID → types.Vertex 216 | , subgraph : types.SubGraph → types.Vertex 217 | } 218 | , subgraph : 219 | { id : Optional Text 220 | , attributes : List Attribute 221 | , statements : List types.Statement 222 | } → 223 | types.SubGraph 224 | } 225 | ) → 226 | constructors.statement.attributes x 227 | , attribute = 228 | λ(x : Attribute) → 229 | λ(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 230 | λ ( constructors 231 | : { statement : 232 | { node : 233 | { nodeID : NodeID, attributes : List Attribute } → 234 | types.Statement 235 | , edges : 236 | { vertices : List types.Vertex 237 | , attributes : List Attribute 238 | } → 239 | types.Statement 240 | , attributes : 241 | { type : AttributeType, attributes : List Attribute } → 242 | types.Statement 243 | , attribute : Attribute → types.Statement 244 | , subgraph : types.SubGraph → types.Statement 245 | } 246 | , vertex : 247 | { nodeID : NodeID → types.Vertex 248 | , subgraph : types.SubGraph → types.Vertex 249 | } 250 | , subgraph : 251 | { id : Optional Text 252 | , attributes : List Attribute 253 | , statements : List types.Statement 254 | } → 255 | types.SubGraph 256 | } 257 | ) → 258 | constructors.statement.attribute x 259 | , subgraph = 260 | λ(x : SubGraph) → 261 | λ(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 262 | λ ( constructors 263 | : { statement : 264 | { node : 265 | { nodeID : NodeID, attributes : List Attribute } → 266 | types.Statement 267 | , edges : 268 | { vertices : List types.Vertex 269 | , attributes : List Attribute 270 | } → 271 | types.Statement 272 | , attributes : 273 | { type : AttributeType, attributes : List Attribute } → 274 | types.Statement 275 | , attribute : Attribute → types.Statement 276 | , subgraph : types.SubGraph → types.Statement 277 | } 278 | , vertex : 279 | { nodeID : NodeID → types.Vertex 280 | , subgraph : types.SubGraph → types.Vertex 281 | } 282 | , subgraph : 283 | { id : Optional Text 284 | , attributes : List Attribute 285 | , statements : List types.Statement 286 | } → 287 | types.SubGraph 288 | } 289 | ) → 290 | constructors.statement.subgraph (x types constructors) 291 | } 292 | 293 | let vertex 294 | : { nodeID : NodeID → Vertex, subgraph : SubGraph → Vertex } 295 | = { nodeID = 296 | λ(x : { id : ID, port : Optional Port }) → 297 | λ(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 298 | λ ( constructors 299 | : { statement : 300 | { node : 301 | { nodeID : NodeID, attributes : List Attribute } → 302 | types.Statement 303 | , edges : 304 | { vertices : List types.Vertex 305 | , attributes : List Attribute 306 | } → 307 | types.Statement 308 | , attributes : 309 | { type : AttributeType, attributes : List Attribute } → 310 | types.Statement 311 | , attribute : Attribute → types.Statement 312 | , subgraph : types.SubGraph → types.Statement 313 | } 314 | , vertex : 315 | { nodeID : NodeID → types.Vertex 316 | , subgraph : types.SubGraph → types.Vertex 317 | } 318 | , subgraph : 319 | { id : Optional Text 320 | , attributes : List Attribute 321 | , statements : List types.Statement 322 | } → 323 | types.SubGraph 324 | } 325 | ) → 326 | constructors.vertex.nodeID x 327 | , subgraph = 328 | λ(x : SubGraph) → 329 | λ(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 330 | λ ( constructors 331 | : { statement : 332 | { node : 333 | { nodeID : NodeID, attributes : List Attribute } → 334 | types.Statement 335 | , edges : 336 | { vertices : List types.Vertex 337 | , attributes : List Attribute 338 | } → 339 | types.Statement 340 | , attributes : 341 | { type : AttributeType, attributes : List Attribute } → 342 | types.Statement 343 | , attribute : Attribute → types.Statement 344 | , subgraph : types.SubGraph → types.Statement 345 | } 346 | , vertex : 347 | { nodeID : NodeID → types.Vertex 348 | , subgraph : types.SubGraph → types.Vertex 349 | } 350 | , subgraph : 351 | { id : Optional Text 352 | , attributes : List Attribute 353 | , statements : List types.Statement 354 | } → 355 | types.SubGraph 356 | } 357 | ) → 358 | constructors.vertex.subgraph (x types constructors) 359 | } 360 | 361 | let subgraph 362 | : { id : Optional ID 363 | , attributes : List Attribute 364 | , statements : List Statement 365 | } → 366 | SubGraph 367 | = λ ( x 368 | : { id : Optional ID 369 | , attributes : List Attribute 370 | , statements : List Statement 371 | } 372 | ) → 373 | λ(types : { Statement : Type, Vertex : Type, SubGraph : Type }) → 374 | λ ( constructors 375 | : { statement : 376 | { node : 377 | { nodeID : NodeID, attributes : List Attribute } → 378 | types.Statement 379 | , edges : 380 | { vertices : List types.Vertex 381 | , attributes : List Attribute 382 | } → 383 | types.Statement 384 | , attributes : 385 | { type : AttributeType, attributes : List Attribute } → 386 | types.Statement 387 | , attribute : Attribute → types.Statement 388 | , subgraph : types.SubGraph → types.Statement 389 | } 390 | , vertex : 391 | { nodeID : NodeID → types.Vertex 392 | , subgraph : types.SubGraph → types.Vertex 393 | } 394 | , subgraph : 395 | { id : Optional Text 396 | , attributes : List Attribute 397 | , statements : List types.Statement 398 | } → 399 | types.SubGraph 400 | } 401 | ) → 402 | constructors.subgraph 403 | { id = x.id 404 | , statements = 405 | let adapt = λ(s : Statement) → s types constructors 406 | 407 | in List/map Statement types.Statement adapt x.statements 408 | , attributes = x.attributes 409 | } 410 | 411 | let Directionality = < graph | digraph > 412 | 413 | let Graph = 414 | { strict : Bool 415 | , directionality : Directionality 416 | , id : Optional ID 417 | , statements : List Statement 418 | } 419 | 420 | in { Attribute 421 | , AttributeType 422 | , CompassPoint 423 | , Directionality 424 | , Graph 425 | , ID 426 | , NodeID 427 | , Port 428 | , SubGraph 429 | , subgraph 430 | , Statement 431 | , statement 432 | , Vertex 433 | , vertex 434 | } 435 | --------------------------------------------------------------------------------