developer tip

논리 프로그래밍과 기능 프로그래밍의 차이점

copycodes 2020. 11. 14. 10:44
반응형

논리 프로그래밍과 기능 프로그래밍의 차이점


나는 함수와 논리 프로그래밍의 차이점을 이해하기 위해 많은 기사를 읽었지만 지금까지 내가 할 수 있었던 유일한 추론은 논리 프로그래밍이 수학적 표현을 통해 프로그램을 정의한다는 것입니다. 그러나 그런 것은 논리 프로그래밍과 관련이 없습니다.

기능적 프로그래밍과 로직 프로그래밍의 차이에 대해 설명해 주시면 감사하겠습니다.


논리 프로그래밍이 수학적 표현을 통해 프로그램을 정의한다고 말하지 않을 것입니다. 함수형 프로그래밍처럼 들립니다. 논리 프로그래밍은 논리 표현식을 사용합니다 (음, 결국 논리는 수학입니다).

내 생각에, 함수형 프로그래밍과 로직 프로그래밍의 주요 차이점은 "빌딩 블록"입니다. 함수형 프로그래밍은 함수를 사용하고 로직 프로그래밍은 술어를 사용합니다. 술어는 함수가 아닙니다. 반환 값이 없습니다. 인수의 값에 따라 참 또는 거짓 일 수 있습니다. 일부 값이 정의되지 않은 경우 술어를 true로 만드는 값을 찾으려고합니다.

특히 프롤로그는 1 차 논리에 속하는 Horn 절 이라는 특수한 형식의 논리 절을 사용합니다 . Hilog는 고차 논리의 절을 사용합니다.

프롤로그 술어를 작성할 때 horn 절을 정의합니다. foo :- bar1, bar2, bar3.즉, bar1, bar2 및 bar3이 참이면 foo가 참임을 의미합니다. 나는 다음과 같은 경우에만 말하지 않았습니다. 하나의 술어에 대해 여러 절을 가질 수 있습니다.

foo:-
   bar1.
foo:-
  bar2.

bar1이 true이거나 bar2가 true이면 foo가 true임을 의미합니다.

어떤 사람들은 논리 프로그래밍이 각 함수가 술어로 표현 될 수 있기 때문에 함수 프로그래밍의 상위 집합이라고 말합니다.

foo(x,y) -> x+y.

다음과 같이 쓸 수 있습니다.

foo(X, Y, ReturnValue):-
   ReturnValue is X+Y.

그러나 나는 그러한 진술이 약간 오해의 소지가 있다고 생각합니다

논리와 기능의 또 다른 차이점은 역 추적입니다. 함수형 프로그래밍에서는 함수 본문을 입력하면 실패 할 수 없으며 다음 정의로 이동할 수 없습니다. 예를 들어 다음과 같이 작성할 수 있습니다.

abs(x) -> 
   if x>0 x else -x

또는 가드를 사용하십시오.

abs(x) x>0 -> x;
abs(x) x=<0 -> -x.

그러나 당신은 쓸 수 없습니다

abs(x) ->
   x>0,
   x;
abs(x) ->
   -x.

반면에 Prolog에서는 다음과 같이 작성할 수 있습니다.

abs(X, R):-
   X>0,
   R is X.
abs(X, R):-
   R is -X.

를 호출 abs(-3, R)하면 Prolog는 첫 번째 절을 시도하고 실행이 -3 > 0지점에 도달하면 실패 하지만 오류가 발생하지 않습니다. Prolog는 두 번째 절을 시도하고을 반환 R = 3합니다.

나는 기능적 언어가 비슷한 것을 구현하는 것이 불가능하다고 생각하지 않습니다 (하지만 그런 언어를 사용하지 않았습니다).

대체로 두 패러다임이 모두 선언적인 것으로 간주되지만 상당히 다릅니다. 너무 다르기 때문에 그것들을 비교하는 것은 기능적 스타일과 명령형 스타일을 비교하는 것처럼 느껴집니다. 나는 약간의 논리 프로그래밍을 시도 할 것을 제안 할 것이다. 놀라운 경험이어야합니다. 그러나 단순히 프로그램을 작성하는 것이 아니라 철학을 이해하려고 노력해야합니다. 프롤로그를 사용하면 기능적 또는 명령 적 스타일로 작성할 수 있습니다 (괴상한 결과 포함).


간단히 말해서 :

함수형 프로그래밍에서 프로그램은 함수 정의의 집합입니다. 각 함수의 반환 값은 전달 된 인수 및 기타 정의 된 함수를 사용할 수있는 수학 표현식으로 평가됩니다. 예를 들어 factorial주어진 숫자의 계승을 반환하는 함수를 정의 할 수 있습니다 .

factorial 0 = 1                       // a factorial of 0 is 1
factorial n = n * factorial (n - 1)   // a factorial of n is n times factorial of n - 1 

논리 프로그래밍에서 프로그램은 술어 세트입니다. 술어는 일반적으로 절의 집합으로 정의되며, 여기서 각 절은 수학적 표현, 기타 정의 된 술어 및 명제 미적분을 사용하여 정의 할 수 있습니다. 예를 들어, 두 번째 인수가 첫 번째 인수 일 때마다 유지되는 '요인'술어를 정의 할 수 있습니다.

factorial(0, 1).               // it is true that a factorial of 0 is 1
factorial(X, Y) :-             // it is true that a factorial of X is Y, when all following are true:
    X1 is X - 1,                   // there is a X1, equal to X - 1,
    factorial(X1, Z),              // and it is true that factorial of X1 is Z, 
    Y is Z * X.                    // and Y is Z * X

두 스타일 모두 프로그램에서 수학적 표현을 사용할 수 있습니다.


첫째, 기능 프로그래밍과 로직 프로그래밍 사이에는 많은 공통점이 있습니다. 즉, 한 커뮤니티에서 개발 된 많은 개념이 다른 커뮤니티에서도 사용될 수 있습니다. 두 패러다임은 다소 조잡한 구현으로 시작되었으며 순수성을 위해 노력합니다.

그러나 차이점을 알고 싶습니다.

그래서 저는 하스켈을 한쪽으로, 프롤로그를 다른쪽에 제약 할 것입니다. 실제로 현재의 모든 Prolog 시스템은 B, Ciao, ECLiPSe, GNU, IF, SICStus, SWI, YAP, XSB와 같은 일종의 제약 조건을 제공합니다. 논쟁을 위해, 나는 dif/2첫 번째 Prolog 구현 에서조차 존재했던 불평등을 의미 하는 매우 간단한 제약 조건을 사용할 것입니다. 그래서 그보다 더 진보 된 것은 사용하지 않을 것입니다.

함수형 프로그래밍이 부족한 것

가장 근본적인 차이점은 변수 개념에 있습니다. 함수형 프로그래밍에서 변수는 구체적인 값을 나타냅니다. 이 값은 완전히 정의되어서는 안되지만 정의 된 부분 만 계산에 사용할 수 있습니다. Haskell에서 고려하십시오.

> let v = iterate (tail) [1..3] 
> v
[[1,2,3],[2,3],[3],[],*** Exception: Prelude.tail: empty list

네 번째 요소 이후에는 값이 정의되지 않습니다. 그럼에도 불구하고 처음 4 개의 요소를 안전하게 사용할 수 있습니다.

> take 4 v
[[1,2,3],[2,3],[3],[]]

함수형 프로그램의 구문은 변수가 정의되지 않은 상태로 유지되는 것을 방지하기 위해 영리하게 제한됩니다.

논리 프로그래밍에서 변수는 구체적인 값을 참조 할 필요가 없습니다. 따라서 3 개의 요소 목록을 원하면 다음과 같이 말할 수 있습니다.

?- length(Xs,3).
Xs = [_G323, _G326, _G329].

이 답변에서 목록의 요소는 변수입니다. 이러한 변수의 가능한 모든 인스턴스는 유효한 솔루션입니다. 처럼 Xs = [1,2,3]. 이제 첫 번째 요소가 나머지 요소와 달라야한다고 가정 해 보겠습니다.

?- length(Xs,3), Xs = [X|Ys], maplist(dif(X), Ys).
Xs = [X, _G639, _G642],
Ys = [_G639, _G642],
dif(X, _G642),
dif(X, _G639).

Later on, we might demand that the elements in Xs are all equal. Before I write it out, I will try it alone:

?- maplist(=(_),Xs).
Xs = [] ;
Xs = [_G231] ;
Xs = [_G231, _G231] ;
Xs = [_G231, _G231, _G231]  ;
Xs = [_G231, _G231, _G231, _G231] .

See that the answers contain always the same variable? Now, I can combine both queries:

?- length(Xs,3), Xs = [X|Ys], maplist(dif(X), Ys), maplist(=(_),Xs).
false.

So what we have shown here is that there is no 3 element list where the first element is different to the other elements and all elements are equal.

This generality has permitted to develop several constraint languages which are offered as libraries to Prolog systems, the most prominent are CLPFD and CHR.

There is no straight forward way to get similar functionality in functional programming. You can emulate things, but the emulation isn't quite the same.

What logic programming is lacking

But there are many things that are lacking in logic programming that make functional programming so interesting. In particular:

Higher-order programming: Functional programming has here a very long tradition and has developed a rich set of idioms. For Prolog, the first proposals date back to the early 1980s, but it is still not very common. At least ISO Prolog has now the homologue to apply called call/2, call/3 ....

Lambdas: Again, it is possible to extend logic programming in that direction, the most prominent system is Lambda Prolog. More recently, lambdas have been developed also for ISO Prolog.

Type systems: There have been attempts, like Mercury, but it has not caught on that much. And there is no system with functionality comparable to type classes.

Purity: Haskell is entirely pure, a function Integer -> Integer is a function. No fine print lurking around. And still you can perform side effects. Comparable approaches are very slowly evolving.

There are many areas where functional and logic programming more or less overlap. For example backtracking and lazyness and list comprehensions, lazy evaluation and freeze/2, when/2, block. DCGs and monads. I will leave discussing these issues to others...


Logic programming and functional programming use different "metaphors" for computation. This often affects how you think about producing a solution, and sometimes means that different algorithms come naturally to a functional programmer than a logic programmer.

Both are based on mathematical foundations that provide more benefits for "pure" code; code that doesn't operate with side effects. There are languages for both paradigms that enforce purity, as well as languages that allow unconstrained side effects, but culturally the programmers for such languages tend to still value purity.

I'm going to consider append, a fairly basic operation in both logical and functional programming, for appending a list on to the end of another list.

In functional programming, we might consider append to be something like this:

append [] ys = ys
append (x:xs) ys = x : append xs ys

While in logic programming, we might consider append to be something like this:

append([], Ys, Ys).
append([X|Xs], Ys, [X|Zs]) :- append(Xs, Ys, Zs).

These implement the same algorithm, and even work basically the same way, but they "mean" something very different.

The functional append defines the list that results from appending ys onto the end of xs. We think of append as a function from two lists to another list, and the runtime system is designed to calculate the result of the function when we invoke it on two lists.

The logical append defines a relationship between three lists, which is true if the third list is the elements of the first list followed by the elements of the second list. We think of append as a predicate that is either true or false for any 3 given lists, and the runtime system is designed to find values that will make this predicate true when we invoke it with some arguments bound to specific lists and some left unbound.

The thing that makes logical append different is you can use it to compute the list that results from appending one list onto another, but you can also use it to compute the list you'd need to append onto the end of another to get a third list (or whether no such list exists), or to compute the list to which you need to append another to get a third list, or to give you two possible lists that can be appended together to get a given third (and to explore all possible ways of doing this).

While equivalent in that you can do anything you can do in one in the other, they lead to different ways of thinking about your programming task. To implement something in functional programming, you think about how to produce your result from the results of other function calls (which you may also have to implement). To implement something in logic programming, you think about what relationships between your arguments (some of which are input and some of which are output, and not necessarily the same ones from call to call) will imply the desired relationship.


Prolog, being a logical language, gives you free backtracking, it's pretty noticeable.

To elaborate, and I precise that I'm in no way expert in any of the paradigms, it looks to me like logical programming is way better when it comes to solving things. Because that's precisely what the language does (that appears clearly when backtracking is needed for example).


I think the difference is this:

  • imperative programming=modelling actions
  • function programming=modelling reasoning
  • logic programming =modelling knowledge

choose what fits your mind best


functional programming: when 6PM, light on. logic programming: when dark, light on.


Difference between functional programming and imperative programming is based on two concepts :-

a:- What to do ? b:- How to do ?

Think a computer like newly born baby now you want that baby to complete a task (What to do?). Now that baby can either know by itself how to achieve that task if he knows than its functional programming. Now if that bay doesn't know how to achieve that task and it needs the programmers help to make a logic for that concept than this is imperitive programming.

참고URL : https://stackoverflow.com/questions/8297574/difference-between-logic-programming-and-functional-programming

반응형