Answers.Body: <p>The advantage of a declarative language like Prolog is that it can be used to express facts and inference rules separately from control flow.  </p>
  
  <p>This allows the developer to focus on the data and inference rules (the knowledge model), and allows the developer to extend the knowledge model more easily.</p>
  
  <p>I should add that in practice, this dichotomy between facts/rules on the one hand, and control flow on the other, is not strict. A knowledge engineer who writes a code base in Prolog does sometimes have to consider control flow. The "!" operator is used so that the developer can influence the evaluation of the rules.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-08-02T19:16:46.910Z
Answers.LastActivityDate: 2016-08-02T19:16:46.910Z
Answers.UserDisplayName: S.L. Barth is on codidact.com
Answers.Body: <p>There's no objective reason to state that declarative languages are better suited for AI development. However, there's indeed a bias towards them in practice. Although most functional languages are impure (that is, they allow side effects), and such can't count as "declarative", a few languages are purely functional (that is, they don't allow side effects), most prominently <a href="https://en.wikipedia.org/wiki/Declarative_programming#Functional_programming" rel="nofollow noreferrer">Haskell</a>. Purity is key here. In Haskell, <a href="https://stackoverflow.com/a/4066401/5249858">even I/O is pure</a>.</p>
  
  <p>The key difference between imperative languages and (purely) functional languages is in the way they describe the program. An imperative program describes <em>how</em> to do stuff, that is, algorithms. It specifies the specific instructions that the machine must carry on in order to perform the computation. OTOH, purely functional languages describe <em>what</em> is to be computed, that is, the relationship between the input and the output. In mathematics, "function" is just a fancy name for a relationship between an input and an output.</p>
  
  <p>Again, in the mathematical sense, the only variability is that of the function's arguments. That is, the function's output depends solely on its input (arguments). This is known as <a href="https://en.wikipedia.org/wiki/Referential_transparency" rel="nofollow noreferrer">referential transparency</a>. Referential transparency states that:</p>
  
  <p><span class="math-container">$$
  \forall f \in \varphi, \forall x \in \delta_f, fx = fx
  $$</span></p>
  
  <p>Where <span class="math-container">$\varphi$</span> is the set of all functions, and <span class="math-container">$\delta_f$</span> is <span class="math-container">$f$</span>'s domain. For the typical imperative language's definition of "function", the above doesn't hold. For instance, C's <code>getchar()</code> does not always return the same value.</p>
  
  <p>Let's say we want to calculate the set of the ten least prime numbers whose least significant digit is <span class="math-container">$3$</span>. First, in mathematical notation:</p>
  
  <p><span class="math-container">$$
  \mathbb{S} = \mathbb{G}_{10} = \{ x \mid x \in \{ p \mid p \in \mathbb{N} \setminus \{0, 1 \} \text{ and } (\forall q \in \mathbb{N} \setminus \{0, 1, p \}, p \text{ mod } q = 0) \},  x \text{ mod } 10 = 3 \}
  $$</span></p>
  
  <p>Where <code>G(n, s)</code> is the set of the lesser <code>n</code>th elements from <code>s</code>. In mathematics, you don't worry about how is the set <span class="math-container">$\mathbb{S}$</span> supposed to be computed, but rather about <span class="math-container">$\mathbb{S}$</span>'s definition itself.</p>
  
  <p>Now, in Python (in imperative style):</p>
  
  <pre><code>def is_prime(n):
    for x in range(2, n):
      if n % x == 0:
        return False
  
    return True
  
  def foo():
    s = set()
    n = 2
    while len(s) &lt; 10:
      if is_prime(n) and n % 10 == 3:
         s.append(n)
  
    return set(s)
  </code></pre>
  
  <p>In Python, we care about (and are responsible for) the algorithm being used to compute the set. We specify, pretty much in recipe-style, how to build the set from scratch. If there's an algorithm that may be better suited for checking whether a number is prime or odd, but we don't use it, it's our fault, not Python's.</p>
  
  <p>Finally, Haskell steps in:</p>
  
  <pre><code>import qualified Data.Set as Set
  
  isPrime :: Integer -&gt; Bool
  isPrime n = ( == 1 ) . length . filter ( == 0 ) . map ( n `mod` ) $ [ 2 .. n ]
  
  s = Set.fromList . take 10 . filter ( ( == 3 ) . ( `mod` 10 ) ) . filter isPrime $ [1..]
  </code></pre>
  
  <p>Haskell's version is a lot more like the mathematical model than Python is. We define the <code>isPrime</code> function in terms of the constraints that a prime number must obey, not by describing a step-by-step algorithm to do such a check. Moreover, <code>s</code> (the set we have been defining so far) is defined in terms of the constraints its members must obey, rather than in terms of an algorithm to compute <code>s</code> itself. The compiler, more often than not <a href="https://downloads.haskell.org/~ghc/7.8.3/docs/html/users_guide/" rel="nofollow noreferrer">The Glorious Glasgow Haskell Compilation System</a> (a.k.a GHC), is the one responsible for generating an algorithm. GHC's optimizer is known to be one of the strongest in the world, not because its the best compiler of 'em all, but because Haskell's nature allows for this.</p>
  
  <p>Haskell (and other functional languages), in summary, have several features that make it look, taste, and behave like pure math:</p>
  
  <ul>
  <li><p>Referential transparency and purity.</p></li>
  <li><p><a href="https://en.wikipedia.org/wiki/Lazy_evaluation" rel="nofollow noreferrer">Haskell is lazy</a>.</p></li>
  <li><p><a href="https://softwareengineering.stackexchange.com/questions/279316/what-exactly-makes-the-haskell-type-system-so-revered-vs-say-java">A <strong>very</strong> strong type system</a>, with such exotic (but very useful!) stuff as <a href="https://en.wikipedia.org/wiki/Recursive_data_type" rel="nofollow noreferrer">recursive</a> (and <a href="https://en.wikipedia.org/wiki/Algebraic_data_type" rel="nofollow noreferrer">algebraic</a>) data types.</p></li>
  </ul>
  
  <p>So, the bottom line is that AI researchers often prefer functional languages over imperative languages (or, more assertively, pure over impure languages), because they are attempting to <em>define</em> artificial intelligence itself, by means of functions (relationship between an input and an output). At the end, we do this because we have no real algorithm for human-level intelligence to raise from a handful of transistors. Also, there's been a historical bias towards these kind of languages, starting with <a href="https://en.wikipedia.org/wiki/John_McCarthy_(computer_scientist)" rel="nofollow noreferrer">John McCarthy</a>, Lisp's creator and a pioneer in early AI research.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2016-08-02T20:37:36.760Z
Answers.LastActivityDate: 2018-11-18T12:34:56.643Z
Answers.LastEditDate: 2018-11-18T12:34:56.643Z
Answers.UserDisplayName: 3442
Body: <p>What specific advantages of declarative languages make them more applicable to AI than imperative languages?  </p>
  
  <p>What can declarative languages do easily that other languages styles find difficult for this kind of problem?</p>
  
Tags: <declarative-programming>
Title: What are the main advantages of using declarative programming languages for building AI?
UserDisplayName: intcreator
ThreadText: # What are the main advantages of using declarative programming languages for building AI?
  
  (Asked by: username_0 on 2016-08-02)
  
  What specific advantages of declarative languages make them more applicable to AI than imperative languages?
  
  What can declarative languages do easily that other languages styles find difficult for this kind of problem?
  
  **Tags:** declarative-programming
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2016-08-02. Score: 5
  
  The advantage of a declarative language like Prolog is that it can be used to express facts and inference rules separately from control flow.
  
  This allows the developer to focus on the data and inference rules (the knowledge model), and allows the developer to extend the knowledge model more easily.
  
  I should add that in practice, this dichotomy between facts/rules on the one hand, and control flow on the other, is not strict. A knowledge engineer who writes a code base in Prolog does sometimes have to consider control flow. The "!" operator is used so that the developer can influence the evaluation of the rules.
  
  
  ---
  
  ### Answer by username_2 on 2016-08-02. Score: 5
  
  There's no objective reason to state that declarative languages are better suited for AI development. However, there's indeed a bias towards them in practice. Although most functional languages are impure (that is, they allow side effects), and such can't count as "declarative", a few languages are purely functional (that is, they don't allow side effects), most prominently Haskell. Purity is key here. In Haskell, even I/O is pure.
  The key difference between imperative languages and (purely) functional languages is in the way they describe the program. An imperative program describes how to do stuff, that is, algorithms. It specifies the specific instructions that the machine must carry on in order to perform the computation. OTOH, purely functional languages describe what is to be computed, that is, the relationship between the input and the output. In mathematics, "function" is just a fancy name for a relationship between an input and an output.
  Again, in the mathematical sense, the only variability is that of the function's arguments. That is, the function's output depends solely on its input (arguments). This is known as referential transparency. Referential transparency states that:
  $$
  \forall f \in \varphi, \forall x \in \delta_f, fx = fx
  $$
  Where $\varphi$ is the set of all functions, and $\delta_f$ is $f$'s domain. For the typical imperative language's definition of "function", the above doesn't hold. For instance, C's getchar() does not always return the same value.
  Let's say we want to calculate the set of the ten least prime numbers whose least significant digit is $3$. First, in mathematical notation:
  $$
  \mathbb{S} = \mathbb{G}_{10} = \{ x \mid x \in \{ p \mid p \in \mathbb{N} \setminus \{0, 1 \} \text{ and } (\forall q \in \mathbb{N} \setminus \{0, 1, p \}, p \text{ mod } q = 0) \},  x \text{ mod } 10 = 3 \}
  $$
  Where G(n, s) is the set of the lesser nth elements from s. In mathematics, you don't worry about how is the set $\mathbb{S}$ supposed to be computed, but rather about $\mathbb{S}$'s definition itself.
  Now, in Python (in imperative style):
  def is_prime(n):
    for x in range(2, n):
      if n % x == 0:
        return False
  
    return True
  
  def foo():
    s = set()
    n = 2
    while len(s) < 10:
      if is_prime(n) and n % 10 == 3:
         s.append(n)
  
    return set(s)
  
  In Python, we care about (and are responsible for) the algorithm being used to compute the set. We specify, pretty much in recipe-style, how to build the set from scratch. If there's an algorithm that may be better suited for checking whether a number is prime or odd, but we don't use it, it's our fault, not Python's.
  Finally, Haskell steps in:
  import qualified Data.Set as Set
  
  isPrime :: Integer -> Bool
  isPrime n = ( == 1 ) . length . filter ( == 0 ) . map ( n `mod` ) $ [ 2 .. n ]
  
  s = Set.fromList . take 10 . filter ( ( == 3 ) . ( `mod` 10 ) ) . filter isPrime $ [1..]
  
  Haskell's version is a lot more like the mathematical model than Python is. We define the isPrime function in terms of the constraints that a prime number must obey, not by describing a step-by-step algorithm to do such a check. Moreover, s (the set we have been defining so far) is defined in terms of the constraints its members must obey, rather than in terms of an algorithm to compute s itself. The compiler, more often than not The Glorious Glasgow Haskell Compilation System (a.k.a GHC), is the one responsible for generating an algorithm. GHC's optimizer is known to be one of the strongest in the world, not because its the best compiler of 'em all, but because Haskell's nature allows for this.
  Haskell (and other functional languages), in summary, have several features that make it look, taste, and behave like pure math:
  
  Referential transparency and purity.
  Haskell is lazy.
  A very strong type system, with such exotic (but very useful!) stuff as recursive (and algebraic) data types.
  
  So, the bottom line is that AI researchers often prefer functional languages over imperative languages (or, more assertively, pure over impure languages), because they are attempting to define artificial intelligence itself, by means of functions (relationship between an input and an output). At the end, we do this because we have no real algorithm for human-level intelligence to raise from a handful of transistors. Also, there's been a historical bias towards these kind of languages, starting with John McCarthy, Lisp's creator and a pioneer in early AI research.
  
  
  ---
  
  