skip to main content
research-article
Free Access

Compositional Programming

Authors Info & Claims
Published:03 September 2021Publication History
Skip Abstract Section

Abstract

Modularity is a key concern in programming. However, programming languages remain limited in terms of modularity and extensibility. Small canonical problems, such as the Expression Problem (EP), illustrate some of the basic issues: the dilemma between choosing one kind of extensibility over another one in most programming languages. Other problems, such as how to express dependencies in a modular way, add up to the basic issues and remain a significant challenge.

This article presents a new statically typed modular programming style called Compositional Programming. In Compositional Programming, there is no EP: It is easy to get extensibility in multiple dimensions (i.e., it is easy to add new variants as well as new operations). Compositional Programming offers an alternative way to model data structures that differs from both algebraic datatypes in functional programming and conventional OOP class hierarchies. We introduce four key concepts for Compositional Programming: compositional interfaces, compositional traits, method patterns, and nested trait composition. Altogether, these concepts allow us to naturally solve challenges such as the Expression Problem, model attribute-grammar-like programs, and generally deal with modular programs with complex dependencies. We present a language design, called CP, which is proved to be type-safe, together with several examples and three case studies.

References

  1. João Alpuim, Bruno C. d. S. Oliveira, and Zhiyuan Shi. 2017. Disjoint polymorphism. In Proceedings of the European Symposium on Programming. Springer, 1–28.Google ScholarGoogle ScholarCross RefCross Ref
  2. Davide Ancona and Elena Zucca. 2002. A calculus of module systems. J. Funct. Prog. 12, 2 (2002), 91–132.Google ScholarGoogle ScholarDigital LibraryDigital Library
  3. Ivica Aracic, Vaidas Gasiunas, Mira Mezini, and Klaus Ostermann. 2006. An overview of CaesarJ. In Transactions on Aspect-oriented Software Development I. Springer, 135–173.Google ScholarGoogle Scholar
  4. Henk Barendregt, Mario Coppo, and Mariangiola Dezani-Ciancaglini. 1983. A filter lambda model and the completeness of type assignment 1. J. Symb. Logic 48, 4 (1983), 931–940.Google ScholarGoogle ScholarCross RefCross Ref
  5. Xuan Bi and Bruno C. d. S. Oliveira. 2018. Typed first-class traits. In Proceedings of the 32nd European Conference on Object-oriented Programming (ECOOP’18). Schloss Dagstuhl-Leibniz-Zentrum fuer Informatik.Google ScholarGoogle Scholar
  6. Xuan Bi, Bruno C. d. S. Oliveira, and Tom Schrijvers. 2018. The essence of nested composition. In Proceedings of the 32nd European Conference on Object-oriented Programming (ECOOP’18). Schloss Dagstuhl-Leibniz-Zentrum fuer Informatik.Google ScholarGoogle Scholar
  7. Xuan Bi, Ningning Xie, Bruno C. d. S. Oliveira, and Tom Schrijvers. 2019. Distributive disjoint polymorphism for compositional programming. In Proceedings of the European Symposium on Programming. Springer, 381–409.Google ScholarGoogle ScholarCross RefCross Ref
  8. Aggelos Biboudis, Nick Palladinos, George Fourtounis, and Yannis Smaragdakis. 2015. Streams a la carte: Extensible pipelines with object algebras. In Proceedings of the 29th European Conference on Object-oriented Programming (ECOOP’15). Schloss Dagstuhl-Leibniz-Zentrum fuer Informatik.Google ScholarGoogle Scholar
  9. Lasse Blaauwbroek. 2017. On the Interaction Between Unrestricted Union and Intersection Types and Computational Effects. Master’s thesis. Technical University Eindhoven.Google ScholarGoogle Scholar
  10. Gilad Bracha. 1992. The Programming Language Jigsaw: Mixins, Modularity and Multiple Inheritance. Ph.D. Dissertation. Dept. of Computer Science, University of Utah.Google ScholarGoogle Scholar
  11. Gilad Bracha and William Cook. 1990. Mixin-based Inheritance. In Proceedings of the European Conference on Object-oriented Programming and on Object-oriented Programming Systems, Languages, and Applications (OOPSLA/ECOOP’90).Google ScholarGoogle Scholar
  12. Gilad Bracha, Peter Von Der Ahé, Vassili Bykov, Yaron Kashai, William Maddox, and Eliot Miranda. 2010. Modules as objects in newspeak. In Proceedings of the European Conference on Object-oriented Programming. Springer, 405–428.Google ScholarGoogle ScholarCross RefCross Ref
  13. K. Bruce, L. Cardelli, G. Castagna, The Hopkins Object Group, G. Leavens, and B. Pierce. 1996. On binary methods. Theor. Pract. Obj. Syst. 1, 3 (1996).Google ScholarGoogle Scholar
  14. Kim Bruce, Martin Odersky, and Philip Wadler. 1998. A statically safe alternative to virtual types. In Proceedings of the European Conference on Object-oriented Programming.Google ScholarGoogle ScholarCross RefCross Ref
  15. R. M. Burstall, D. B. MacQueen, and D. T. Sannella. 1981. HOPE: An Experimental Applicative Language. Technical Report CSR-62-80. Computer Science Dept, University of Edinburgh.Google ScholarGoogle Scholar
  16. Luca Cardelli. 1994. Extensible Records in a Pure Calculus of Subtyping. The MIT Press, Cambridge, MA.Google ScholarGoogle Scholar
  17. Luca Cardelli and John Mitchell. 1991. Operations on records. Math. Struct. Comput. Sci. 1 (1991), 3–48.Google ScholarGoogle ScholarCross RefCross Ref
  18. Jacques Carette, Oleg Kiselyov, and Chung-chieh Shan. 2009. Finally tagless, partially evaluated: Tagless staged interpreters for simpler typed languages. J. Funct. Prog. 19, 05 (2009), 509–543. DOI:https://doi.org/10.1017/S0956796809007205Google ScholarGoogle ScholarDigital LibraryDigital Library
  19. James Cheney and Ralf Hinze. 2002. A lightweight implementation of generics and dynamics. In Proceedings of the ACM SIGPLAN Workshop on Haskell (Haskell’02), Manuel M. T. Chakravarty (Ed.). ACM, New York, NY, 90–104. DOI:https://doi.org/10.1145/581690.581698Google ScholarGoogle ScholarDigital LibraryDigital Library
  20. Adam Chlipala. 2010. Ur: Statically-typed metaprogramming with type-level record computation. ACM SIGPLAN Not. 45, 6 (2010), 122–133.Google ScholarGoogle ScholarDigital LibraryDigital Library
  21. Dave Clarke, Sophia Drossopoulou, James Noble, and Tobias Wrigstad. 2007. Tribe: A simple virtual class calculus. In Proceedings of the 6th International Conference on Aspect-oriented Software Development. 121–134.Google ScholarGoogle ScholarDigital LibraryDigital Library
  22. William Cook and Jens Palsberg. 1989. A denotational semantics of inheritance and its correctness. In Proceedings of the Conference on Object-oriented Programming Systems, Languages, and Applications (OOPSLA’89). ACM, New York, NY, 433–443. DOI:https://doi.org/10.1145/74877.74922Google ScholarGoogle ScholarDigital LibraryDigital Library
  23. Stephen Dolan and Alan Mycroft. 2017. Polymorphism, subtyping, and type inference in MLsub. In Proceedings of the 44th ACM SIGPLAN Symposium on Principles of Programming Languages (POPL’17). ACM, New York, NY, 60–72. DOI:https://doi.org/10.1145/3009837.3009882Google ScholarGoogle ScholarDigital LibraryDigital Library
  24. Dominic Duggan and Constantinos Sourelis. 1996. Mixin modules. ACM SIGPLAN Not. 31, 6 (1996), 262–273.Google ScholarGoogle ScholarDigital LibraryDigital Library
  25. Joshua Dunfield. 2014. Elaborating intersection and union types. J. Funct. Prog. 24, 2-3 (2014), 133–165. DOI:https://doi.org/10.1017/S0956796813000270Google ScholarGoogle ScholarCross RefCross Ref
  26. Erik Ernst. 1999. gbeta-a Language with Virtual Attributes, Block Structure, and Propagating, Dynamic Inheritance. Ph.D. Dissertation. University of Aarhus.Google ScholarGoogle Scholar
  27. Erik Ernst. 2001. Family polymorphism. In Proceedings of the 15th European Conference on Object-oriented Programming (ECOOP’01).Google ScholarGoogle ScholarDigital LibraryDigital Library
  28. Erik Ernst. 2004. The expression problem, Scandinavian style. In Proceedings of the On Mechanisms for Specialization. 27.Google ScholarGoogle Scholar
  29. Erik Ernst, Klaus Ostermann, and William R. Cook. 2006. A virtual class calculus. In Proceedings of the 33rd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL’06).Google ScholarGoogle Scholar
  30. Matthew Flatt, Shriram Krishnamurthi, and Matthias Felleisen. 1998. Classes and mixins. In Proceedings of the 25th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages. 171–183.Google ScholarGoogle ScholarDigital LibraryDigital Library
  31. Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. 1994. Design Patterns: Elements of Reusable Object-oriented Software. Addison-Wesley.Google ScholarGoogle ScholarDigital LibraryDigital Library
  32. Jacques Garrigue. 2000. Code reuse through polymorphic variants. In Proceedings of the Workshop on Foundations of Software Engineering.Google ScholarGoogle Scholar
  33. Jeremy Gibbons and Nicolas Wu. 2014. Folding domain-specific languages: Deep and shallow embeddings (functional Pearl). In Proceedings of the 19th ACM SIGPLAN International Conference on Functional Programming (ICFP’14). 339–347. DOI:https://doi.org/10.1145/2628136.2628138Google ScholarGoogle ScholarDigital LibraryDigital Library
  34. John V. Guttag and James J. Horning. 1978. The algebraic specification of abstract data types. Acta Inform. 10, 1 (1978), 27–52.Google ScholarGoogle ScholarDigital LibraryDigital Library
  35. William Harrison and Harold Ossher. 1993. Subject-oriented programming: A critique of pure objects. In Proceedings of the 8th Conference on Object-oriented Programming Systems, Languages, and Applications. 411–428.Google ScholarGoogle ScholarDigital LibraryDigital Library
  36. Ralf Hinze. 2004. An algebra of scans. In Mathematics of Program Construction. Springer Berlin Heidelberg, 186–210. DOI:https://doi.org/10.1007/978-3-540-27764-4_11Google ScholarGoogle Scholar
  37. Ralf Hinze. 2006. Generics for the masses. J. Funct. Prog. 16, 4-5 (2006), 451–483. DOI:https://doi.org/10.1017/S0956796806006022Google ScholarGoogle ScholarDigital LibraryDigital Library
  38. Christian Hofer, Klaus Ostermann, Tillmann Rendel, and Adriaan Moors. 2008. Polymorphic embedding of DSLs. In Proceedings of the 7th International Conference on Generative Programming and Component Engineering (GPCE’08).Google ScholarGoogle ScholarDigital LibraryDigital Library
  39. Xuejing Huang and Bruno C. d. S. Oliveira. 2020. A type-directed operational semantics for a calculus with a merge operator. In Proceedings of the 34th European Conference on Object-oriented Programming (ECOOP’20)(Leibniz International Proceedings in Informatics (LIPIcs), Vol. 166). DOI:https://doi.org/10.4230/LIPIcs.ECOOP.2020.26Google ScholarGoogle Scholar
  40. Atsushi Igarashi and Benjamin C. Pierce. 1999. Foundations for virtual types. In Proceedings of the European Conference on Object-oriented Programming. Springer, 161–185.Google ScholarGoogle Scholar
  41. Atsushi Igarashi, Chieri Saito, and Mirko Viroli. 2005. Lightweight family polymorphism. In Proceedings of the Asian Symposium on Programming Languages and Systems. Springer, 161–177.Google ScholarGoogle ScholarDigital LibraryDigital Library
  42. Pablo Inostroza and Tijs van der Storm. 2015. Modular interpreters for the masses: Implicit context propagation using object algebras. In Proceedings of the ACM SIGPLAN International Conference on Generative Programming: Concepts and Experiences.Google ScholarGoogle Scholar
  43. Mauro Jaskelioff. 2008. Monatron: An extensible monad transformer library. In Proceedings of the Symposium on Implementation and Application of Functional Languages. Springer, 233–248.Google ScholarGoogle Scholar
  44. Paul Jolly, Sophia Drossopoulou, Christopher Anderson, and Klaus Ostermann. 2004. Simple dependent types: Concord. In Proceedings of the ECOOP Workshop on Formal Techniques for Java Programs (FTfJP’04).Google ScholarGoogle Scholar
  45. Uwe Kastens and William M. Waite. 1994. Modularity and reusability in attribute grammars. Acta Inform. 31, 7 (1994), 601–627.Google ScholarGoogle ScholarDigital LibraryDigital Library
  46. Gregor Kiczales, John Lamping, Anurag Mendhekar, Chris Maeda, Cristina Lopes, Jean-Marc Loingtier, and John Irwin. 1997. Aspect-oriented programming. In Proceedings of the European Conference on Object-oriented Programming. Springer, 220–242.Google ScholarGoogle ScholarCross RefCross Ref
  47. Jorgen Lindskov Knudsen, Boris Magnusson, Mats Lofgren, and Ole L. Madsen. 1994. Object Oriented Software Development Environments: The Mjolner Approach. Prentice-Hall, Inc.Google ScholarGoogle Scholar
  48. Donald E. Knuth. 1968. Semantics of context-free languages. Math. Syst. Theor. 2, 2 (1968), 127–145.Google ScholarGoogle ScholarCross RefCross Ref
  49. Donald E. Knuth. 1990. The genesis of attribute grammars. In Proceedings of the International Conference WAGA on Attribute Grammars and their Applications. 1–12.Google ScholarGoogle ScholarDigital LibraryDigital Library
  50. Giovanni Lagorio, Marco Servetto, and Elena Zucca. 2009. Featherweight jigsaw: A minimal core calculus for modular composition of classes. In Proceedings of the European Conference on Object-oriented Programming. Springer, 244–268.Google ScholarGoogle ScholarDigital LibraryDigital Library
  51. Joseph Lee, Jonathan Aldrich, Troy Shaw, and Alex Potanin. 2015. A theory of tagged objects. In Proceedings of the 29th European Conference on Object-oriented Programming (ECOOP’15). Schloss Dagstuhl-Leibniz-Zentrum fuer Informatik.Google ScholarGoogle Scholar
  52. Daan Leijen. 2005. Extensible records with scoped labels. Trends Funct. Prog. 6 (2005), 179–194.Google ScholarGoogle Scholar
  53. Sheng Liang, Paul Hudak, and Mark Jones. 1995. Monad transformers and modular interpreters. In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages. 333–343.Google ScholarGoogle ScholarDigital LibraryDigital Library
  54. David MacQueen. 1984. Modules for standard ML. In Proceedings of the ACM Symposium on LISP and Functional Programming. 198–207.Google ScholarGoogle ScholarDigital LibraryDigital Library
  55. Ole Lehrmann Madsen and Birger Moller-Pedersen. 1989. Virtual classes: A powerful mechanism in object-oriented programming. In Proceedings of the Conference on Object-oriented Programming Systems, Languages, and Applications. 397–406.Google ScholarGoogle ScholarDigital LibraryDigital Library
  56. Ole Lehrmann Madsen, Birger Møller-Pedersen, and Kristen Nygaard. 1993. Object-oriented Programming in the BETA Programming Language. Addison-Wesley.Google ScholarGoogle Scholar
  57. Bertrand Meyer. 1988. Object-oriented Software Construction. Prentice Hall.Google ScholarGoogle ScholarDigital LibraryDigital Library
  58. Keiko Nakata and Jacques Garrigue. 2006. Recursive modules for programming. ACM SIGPLAN Not. 41, 9 (2006), 74–86.Google ScholarGoogle ScholarDigital LibraryDigital Library
  59. Nathaniel Nystrom, Stephen Chong, and Andrew C. Myers. 2004. Scalable extensibility via nested inheritance. In Proceedings of the 19th ACM SIGPLAN Conference on Object-oriented Programming, Systems, Languages, and Applications. 99–115.Google ScholarGoogle Scholar
  60. Nathaniel Nystrom, Xin Qi, and Andrew C. Myers. 2006. J& nested intersection for scalable software composition. ACM SIGPLAN Not. 41, 10 (2006), 21–36.Google ScholarGoogle ScholarDigital LibraryDigital Library
  61. Martin Odersky, Philippe Altherr, Vincent Cremet, Burak Emir, Sebastian Maneth, Stéphane Micheloud, Nikolay Mihaylov, Michel Schinz, Erik Stenman, and Matthias Zenger. 2004. An Overview of the Scala Programming Language. Technical Report. EPFL Lausanne, Switzerland.Google ScholarGoogle Scholar
  62. Martin Odersky and Matthias Zenger. 2005. Scalable component abstractions. In Proceedings of the 20th ACM SIGPLAN Conference on Object-oriented Programming, Systems, Languages, and Applications (OOPSLA’05).Google ScholarGoogle ScholarDigital LibraryDigital Library
  63. Bruno C. d. S. Oliveira and William R. Cook. 2012. Extensibility for the masses: Practical extensibility with object algebras. In Proceedings of the 26th European Conference on Object-oriented Programming (ECOOP’12). DOI:https://doi.org/10.1007/978-3-642-31057-7_2Google ScholarGoogle Scholar
  64. Bruno C. d. S. Oliveira, Ralf Hinze, and Andres Löh. 2006. Extensible and modular generics for the masses. In Trends in Functional Programming. 199–216.Google ScholarGoogle Scholar
  65. Bruno C. d. S. Oliveira, Zhiyuan Shi, and João Alpuim. 2016. Disjoint intersection types. In Proceedings of the 21st ACM SIGPLAN International Conference on Functional Programming. 364–377.Google ScholarGoogle ScholarDigital LibraryDigital Library
  66. Bruno C. d. S. Oliveira, Tijs van der Storm, Alex Loh, and William R. Cook. 2013. Feature-oriented programming with object algebras. In Proceedings of the 27th European Conference on Object-oriented Programming. DOI:https://doi.org/10.1007/978-3-642-39038-8_2Google ScholarGoogle Scholar
  67. Benjamin C. Pierce and David N. Turner. 2000. Local type inference. ACM Trans. Prog. Lang. Syst. 22, 1 (Jan. 2000), 44.Google ScholarGoogle ScholarDigital LibraryDigital Library
  68. Klaus Pohl, Günter Böckle, and Frank J. van Der Linden. 2005. Software Product Line Engineering: Foundations, Principles and Techniques. Springer Science & Business Media.Google ScholarGoogle ScholarDigital LibraryDigital Library
  69. Erik Poll. 1997. System F with width-subtyping and record updating. In Proceedings of the 3rd International Symposium on Theoretical Aspects of Computer Software (TACS’97). Springer-Verlag, Berlin.Google ScholarGoogle ScholarCross RefCross Ref
  70. Christian Prehofer. 1997. Feature-oriented programming: A fresh look at objects. In Proceedings of the European Conference on Object-oriented Programming. Springer, 419–443.Google ScholarGoogle ScholarCross RefCross Ref
  71. Tillmann Rendel, Jonathan Immanuel Brachthäuser, and Klaus Ostermann. 2014. From object algebras to attribute grammars. In Proceedings of the ACM International Conference on Object-oriented Programming Systems, Languages, and Applications.Google ScholarGoogle ScholarDigital LibraryDigital Library
  72. Claudio V. Russo. 2000. First-class structures for Standard ML. In Proceedings of the European Symposium on Programming. Springer, 336–350.Google ScholarGoogle ScholarCross RefCross Ref
  73. Claudio V. Russo. 2001. Recursive structures for Standard ML. In Proceedings of the 6th ACM SIGPLAN International Conference on Functional Programming. 50–61.Google ScholarGoogle ScholarDigital LibraryDigital Library
  74. Nathanael Schärli, Stéphane Ducasse, Oscar Nierstrasz, and Andrew P. Black. 2003. Traits: Composable units of behaviour. In Proceedings of the European Conference on Object-oriented Programming. Springer, 248–274.Google ScholarGoogle Scholar
  75. Tom Schrijvers and Bruno C. d. S. Oliveira. 2011. Monads, zippers and views: Virtualizing the monad stack. In Proceedings of the 16th ACM SIGPLAN International Conference on Functional Programming. 32–44.Google ScholarGoogle Scholar
  76. M. Sulzmann, M. M. T. Chakravarty, S. L. Peyton-Jones, and K. Donnelly. 2007. System F with type equality coercions. In Proceedings of the ACM SIGPLAN Workshop on Types in Language in Design and Implementation.Google ScholarGoogle Scholar
  77. Wouter Swierstra. 2008. Data Types à la Carte. J. Funct. Prog. 18, 04 (2008), 423–436. DOI:https://doi.org/10.1017/S0956796808006758Google ScholarGoogle ScholarDigital LibraryDigital Library
  78. Asumu Takikawa, T. Stephen Strickland, Christos Dimoulas, Sam Tobin-Hochstadt, and Matthias Felleisen. 2012. Gradual typing for first-class classes. In Proceedings of the ACM International Conference on Object-oriented Programming Systems, Languages, and Applications. 793–810.Google ScholarGoogle ScholarDigital LibraryDigital Library
  79. Peri Tarr, Harold Ossher, William Harrison, and Stanley M. Sutton. 1999. N degrees of separation: Multi-dimensional separation of concerns. In Proceedings of the International Conference on Software Engineering. IEEE, 107–119.Google ScholarGoogle Scholar
  80. Mads Torgersen. 2004. The expression problem revisited. In Proceedings of the European Conference on Object-oriented Programming (ECOOP’04).Google ScholarGoogle ScholarCross RefCross Ref
  81. Birthe van den Berg. 2020. ICFP: G: Type Inference for Disjoint Intersection Types. https://people.cs.kuleuven.be/ birthe.vandenberg/cite_SRC.html.Google ScholarGoogle Scholar
  82. Philip Wadler. 1992. The essence of functional programming. InProceedings of the ACM SIGPLAN Symposium on Principles of Programming Languages. 1–14.Google ScholarGoogle ScholarDigital LibraryDigital Library
  83. Philip Wadler. 1998. The Expression Problem. (Nov. 1998). Note to Java Genericity mailing list.https://homepages.inf.ed.ac.uk/wadler/papers/expression/expression.txt.Google ScholarGoogle Scholar
  84. Yanlin Wang and Bruno C. d. S. Oliveira. 2016. The expression problem, trivially! In Proceedings of the 15th International Conference on Modularity (MODULARITY’16). 37–41. DOI:https://doi.org/10.1145/2889443.2889448Google ScholarGoogle Scholar
  85. Mathhias Zenger and Martin Odersky. 2005. Independently extensible solutions to the expression problem. In Proceedings of the Foundations of Object-oriented Languages Conference (FOOL’05).Google ScholarGoogle Scholar
  86. Weixin Zhang and Bruno C. d. S. Oliveira. 2017. EVF: An extensible and expressive visitor framework for programming language reuse. In Proceedings of the 31st European Conference on Object-oriented Programming. DOI:https://doi.org/10.4230/LIPIcs.ECOOP.2017.29Google ScholarGoogle Scholar
  87. Weixin Zhang and Bruno C. d. S. Oliveira. 2019. Shallow EDSLs and object-oriented programming: Beyond simple compositionality. Art, Sci., Eng. Prog. 3, 3 (2019), 1–25.Google ScholarGoogle ScholarDigital LibraryDigital Library
  88. Yizhou Zhang and Andrew C. Myers. 2017. Familia: Unifying interfaces, type classes, and family polymorphism. Proc. ACM Prog. Lang. 1, OOPSLA (2017), 1–31.Google ScholarGoogle Scholar

Index Terms

  1. Compositional Programming

    Recommendations

    Comments

    Login options

    Check if you have access through your login credentials or your institution to get full access on this article.

    Sign in

    Full Access

    • Published in

      cover image ACM Transactions on Programming Languages and Systems
      ACM Transactions on Programming Languages and Systems  Volume 43, Issue 3
      September 2021
      239 pages
      ISSN:0164-0925
      EISSN:1558-4593
      DOI:10.1145/3481687
      Issue’s Table of Contents

      Copyright © 2021 Association for Computing Machinery.

      Publisher

      Association for Computing Machinery

      New York, NY, United States

      Publication History

      • Published: 3 September 2021
      • Accepted: 1 April 2021
      • Received: 1 October 2020
      Published in toplas Volume 43, Issue 3

      Permissions

      Request permissions about this article.

      Request Permissions

      Check for updates

      Qualifiers

      • research-article
      • Refereed

    PDF Format

    View or Download as a PDF file.

    PDF

    eReader

    View online with eReader.

    eReader

    HTML Format

    View this article in HTML Format .

    View HTML Format
    About Cookies On This Site

    We use cookies to ensure that we give you the best experience on our website.

    Learn more

    Got it!