맨위로가기

OCaml

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

OCaml은 ML 계열의 다중 패러다임 프로그래밍 언어이며, 함수형, 명령형, 객체 지향 프로그래밍을 지원한다. 1970년대 ML(Meta Language) 개발을 기반으로 시작되어, Caml, Caml Light, Caml Special Light를 거쳐 1996년 Objective Caml로 발전했고, 2011년 OCaml로 명칭이 변경되었다. 정적 타입 시스템, 타입 추론, 패턴 매칭, 클로저, 가비지 컬렉션 등 다양한 기능을 제공하며, 네이티브 코드 컴파일러를 통해 성능을 강조한다. OCaml은 MetaOCaml, F#, Reason 등의 파생 언어를 낳았으며, Ahrefs, Coq, Facebook의 Flow, Hack, Infer, MirageOS, Tezos 등 다양한 소프트웨어 개발에 사용된다.

더 읽어볼만한 페이지

  • 1996년 개발된 프로그래밍 언어 - VB스크립트
    VB스크립트는 마이크로소프트에서 개발한 스크립트 언어로, 인터넷 익스플로러의 클라이언트 스크립트 언어 및 액티브 서버 페이지의 표준 언어로 사용되었으나, 윈도우 클라이언트 지원 중단 발표로 향후 윈도우 릴리스에서 제거될 예정이다.
  • 1996년 개발된 프로그래밍 언어 - SQL/PSM
  • ML 프로그래밍 언어 계열 - ML (프로그래밍 언어)
    ML은 1970년대 초에 개발된 프로그래밍 언어로, 강력한 타입 시스템, 일급 함수, 가비지 컬렉션, 정적 타이핑 등의 기능을 제공하며 다양한 분야에서 활용된다.
  • ML 프로그래밍 언어 계열 - F 샤프
    F#은 .NET 플랫폼에서 실행되는 크로스 플랫폼, 오픈 소스 프로그래밍 언어로서 함수형, 명령형, 객체 지향 프로그래밍을 지원하며 데이터 분석, 웹 개발, 앱 개발 등 다양한 분야에서 활용된다.
  • 패턴 매칭 프로그래밍 언어 - AWK
    AWK는 1977년에 개발된 텍스트 처리 및 프로그래밍 언어로, 유닉스 환경에서 텍스트 처리를 위해 설계되었으며 정규 표현식 처리 기능을 통해 텍스트 분석, 데이터 추출, 보고서 생성 등 다양한 작업을 수행한다.
  • 패턴 매칭 프로그래밍 언어 - 하스켈
    하스켈은 해스켈 커리의 이름을 딴 순수 함수형 프로그래밍 언어로, 여러 함수형 언어 통합 노력의 결과로 탄생하여 느긋한 계산법, 패턴 매칭, 타입 클래스, 모나드 등의 특징을 가지며 GHC가 표준 구현체로 사용된다.
OCaml - [IT 관련 정보]에 관한 문서
기본 정보
이름OCaml
OCaml 로고
패러다임멀티 패러다임: 함수형, 명령형, 모듈형, 객체 지향
계열ML: Caml
개발 시작1996년
설계자Xavier Leroy, Jérôme Vouillon, Damien Doligez, Didier Rémy, Ascánder Suárez
개발자Inria
최신 안정화 버전5.2.0
최신 안정화 버전 출시일2024년 1월 30일 ()
타이핑추론, 정적, 강력, 구조적
구현 언어OCaml, C
플랫폼IA-32, x86-64, Power, SPARC, ARM 32-64, RISC-V
운영 체제크로스 플랫폼: 리눅스, 유닉스, macOS, 윈도우
라이선스LGPLv2.1
파일 확장자.ml, .mli
영향을 받은 언어C, Caml, Modula-3, Pascal, Standard ML
영향을 준 언어ATS, Coq, Elm, F#, F*, Haxe, Opa, Rust, Scala, 리즌
웹사이트OCaml 공식 웹사이트

2. History

OCaml 개발팀이 프로그래밍 언어 원리 심포지엄(POPL) 2024에서 상을 받고 있다.


OCaml은 원래 Caml이라는 이름의 ML 방언 처리 시스템 및 언어였다. 이 이름은 categorical abstract machine languageeng의 약자로, 범주론적 추상 기계(Categorical Abstract Machine) 개념에서 유래했다. 이후 더 효율적인 추상 기계를 기반으로 재작성되었고, 클래스와 상속 등 객체 지향 기능이 추가되면서 Objective Camleng이라는 이름이 되었다. 현재의 공식 명칭 OCaml은 이 Objective Caml의 약칭에서 비롯되었다. 공식 웹사이트에서는 "OCaml은 Caml 파생 언어 중에서 가장 널리 알려져 있다"[39]고 설명한다.

초기의 Caml 처리 시스템은 Caml Light라는 이름으로 계속 배포되고 있다. 영어권에서는 Caml을 cameleng(낙타)과 동일하게 발음하기 때문에, OCaml의 아이콘 등에도 낙타가 사용된다. OCaml은 함수형 언어의 특징과 객체 지향 언어의 특징을 함께 가지고 있으며, 비교적 빠른 실행 속도를 보이는 것으로 알려져 있다[40].

2. 1. Development of ML (Meta Language)



1970년대와 1980년대 사이, 영국의 컴퓨터 과학자이자 튜링상 수상자인 로빈 밀너는 에든버러 대학교의 컴퓨터 과학 기초 연구소에서 연구 활동을 수행했다.[8][9] 밀너와 동료 연구자들은 정리 증명기를 연구했는데, 이는 주로 Lisp와 같은 언어로 개발되었다. 연구 과정에서 밀너는 정리 증명기가 유효하지 않은 증명을 유효한 것으로 잘못 처리하는 문제에 반복적으로 직면했다.[9]

이 문제를 해결하기 위해 밀너는 계산 가능한 함수를 위한 논리(LCF, Logic for Computable Functions)를 위한 메타 언어(ML, Meta Language)를 개발했다. ML은 강력한 다형성 타입 시스템을 특징으로 하여, 프로그래머가 논리적으로 유효한 증명만을 구성하도록 유도했다.[10] ML은 초기에 LCF 시스템을 다른 컴퓨터 환경에서도 쉽게 사용할 수 있도록 컴파일러 형태로 구현되었으며, 1980년대에 이르러서는 독자적인 프로그래밍 시스템으로 발전했다.[10] 이 ML 언어는 훗날 OCaml이 탄생하는 중요한 기반이 되었다.

1980년대 초, ML 언어는 프랑스 학계의 주목을 받기 시작했다. 프랑스 국립 전산 및 자동화 연구소(INRIA)의 Formel 팀은 ML에 관심을 보였다. 이 시기 옥스퍼드 대학교의 루카 카르델리는 '함수 추상 기계'(Functional Abstract Machine)를 이용하여 더 빠른 ML 구현을 개발했고, 로빈 밀너는 여러 구현 간의 호환성 문제를 해결하기 위해 ML의 표준 정의를 제안했다. 동시에 파리 디드로 대학교의 피에르-루이 큐리엔은 람다 계산법과 연결되는 범주적 조합기(Categorical Combinators) 이론을 발전시켜 '범주적 추상 머신'(CAM, Categorical Abstract Machine) 개념을 정립했다. 같은 대학의 기 쿠시노는 이 CAM이 ML 언어를 효율적으로 컴파일하는 방법이 될 수 있음을 발견했다.[11] 이러한 연구 결과는 CAM을 기반으로 하는 새로운 ML 방언인 Caml(Categorical Abstract Machine Language)의 탄생으로 이어졌다.

2. 2. First implementation

Caml은 처음에 제라르 위엣이 이끄는 INRIA의 Formel 팀에 의해 설계 및 개발되었다. Caml의 첫 번째 구현은 1987년에 만들어졌으며 1992년까지 추가 개발이 이루어졌다. 아스칸데르 수아레스가 개발을 주도했으나, 그가 1988년에 떠난 후 피에르 바이스와 미셸 모니가 개발을 이어갔다.[11]

기 쿠지노는 자신의 프로그래밍 언어 구현 경험이 처음에는 매우 제한적이었으며, 자신이 책임져야 할 여러 부적절한 점이 있었다고 회상한다. 그럼에도 불구하고 그는 "아스칸데르, 피에르, 미셸은 꽤 훌륭한 작업을 했다"고 평가했다.[11]

2. 3. Caml Light



Caml Light는 1990년에서 1991년 사이에 자비에 르로이가 C 언어로 작성된 바이트코드 인터프리터를 기반으로 설계한 새로운 Caml 구현체이다. 이 구현에는 다미앙 돌리제가 개발한 순차적 가비지 컬렉션 시스템이 적용되어 메모리 관리가 개선되었다.[10]

Caml Light는 이전 Caml 구현체를 대체했으며, 소형 데스크톱 컴퓨터에서도 실행될 수 있었다.[11] 이후 미셸 모니의 구문 조작 도구 등 여러 라이브러리가 개발되면서 교육 및 연구 분야에서 Caml의 활용이 더욱 확산되었다.[10]

Caml Light는 OCaml의 직접적인 전신이며, 현재도 이 이름으로 계속 배포되고 있다.[42] 또한, SML 처리기 구현[42]이나 연구 목적으로 개조된 OchaCaml 등 다른 프로젝트의 기반으로 사용되기도 한다.

2. 4. Caml Special Light

1995년, 자비에 르로이는 Caml의 개선된 버전인 Caml Special Light를 출시했다.[11] 네이티브 코드 컴파일러가 바이트코드 컴파일러에 추가되어 C++와 같은 주류 언어와 비슷한 수준으로 성능이 크게 향상되었다.[10][11] 또한 르로이는 Standard ML의 모듈 시스템에서 영감을 받아, 추상화와 매개변수화에 강력한 기능을 제공하고 대규모 프로그램을 더 쉽게 구축할 수 있는 고급 모듈 시스템을 설계했다.[10]

2. 5. Objective Caml



디디에 레미(Didier Rémy)와 제롬 부이용(Jérôme Vouillon)은 객체와 클래스를 위한 표현력이 풍부한 타입 시스템을 설계하여 Caml Special Light에 통합했다. 이를 바탕으로 1996년에 Objective Caml 언어가 처음 출시되었고, 2011년에는 OCaml로 이름이 변경되었다. Objective Caml의 객체 시스템은 C++자바 등에서 불안정하거나 런타임 검사가 필요했던 객체 지향적 특징들을 정적 타입 검사를 통해 안전하게 지원하는 장점이 있었다.

2000년에는 자크 가리그(Jacques Garrigue)가 다형성 메서드(polymorphic methods), 변형(variants), 레이블(labels) 및 선택적 인수(optional arguments) 등 여러 새로운 기능을 추가하여 Objective Caml을 더욱 확장했다.[10][11]

원래 이름인 Caml은 'categorical abstract machine language'의 약자였으나(범주론적 추상 기계 참조), 이후 더 효율적인 추상 기계를 기반으로 재작성되고 클래스 기반객체 지향 기능인 클래스와 상속이 추가되면서 Objective Caml이라는 이름이 되었다. 현재 공식 명칭인 OCaml은 Objective Caml의 약칭에서 유래했으며, 공식 웹사이트에서는 "OCaml은 Caml 파생 언어 중에서 가장 널리 알려져 있다"[39]고 설명한다. 원래의 Caml 처리 시스템은 Caml Light라는 이름으로 계속 배포되고 있다. 영어권에서는 Caml을 낙타(camel)와 동일하게 발음하며, OCaml의 아이콘 등에도 낙타 그림이 사용된다.

Objective Caml은 ML의 특징을 계승하면서도 함수형 프로그래밍과 객체 지향 프로그래밍을 모두 지원하는 것이 특징이다. 다만 이로 인해 객체 지향을 사용한 파괴적 조작(상태 변경)을 포함하는 프로그램을 비교적 쉽게 작성할 수도 있다. 또한, 다형성 변형 타입(polymorphic variants)이라는 특별한 대수적 데이터 타입을 통해, 일반적인 변형 타입보다 유연하게 서브셋과 슈퍼셋 관계에 있는 변형 타입 등을 기술할 수 있다.

처리 시스템으로서 OCaml은 함수형 언어 중에서는 상당히 빠른 실행 속도를 보여주며, gcc로 컴파일된 C 언어 프로그램과 비슷하거나 약간 느린 정도의 성능을 낸다고 알려져 있다[40]. 함수형 언어임에도 비교적 다양한 분야에서 응용 프로그램 개발에 사용되고 있다. 예를 들어, 미디어위키에서 TeX 표기법으로 작성된 수식을 HTML, MathML, 이미지 형식으로 변환하는 프로그램도 OCaml로 작성되었다[41].

2. 6. Ongoing development



지난 20년 동안 OCaml의 상업 및 학술 코드베이스 성장을 지원하기 위해 언어 개선 사항이 점진적으로 추가되었다.[10] 2012년 OCaml 4.0 릴리스는 언어의 유연성을 높이기 위해 일반화된 대수적 데이터 유형(GADTs)과 일급 모듈을 추가했다.[10]

2022년에는 OCaml 5.0.0이 릴리스되었다.[12] 이 버전에서는 언어 런타임을 완전히 다시 작성하여 전역 GC 잠금을 제거하고, 제한된 연속체를 통해 효과 처리기를 추가했다. 이러한 변경으로 공유 메모리 병렬 처리와 색상 맹 컨커런시를 지원할 수 있게 되었다.

OCaml의 개발은 INRIA의 Cristal 팀에서 시작되어 2005년까지 이어졌고, 이후 Gallium 팀이 계승했다.[13] 2019년에는 Gallium 팀을 이어 Cambium 팀이 개발을 맡게 되었다.[14][15] 2023년 기준으로, 다양한 조직에 소속된 23명의 컴파일러 배포판 핵심 개발자가 있으며,[16] 더 넓은 OCaml 도구 및 패키징 생태계를 위해 41명의 개발자가 활동하고 있다.[17]

2023년 OCaml 컴파일러는 ACM SIGPLAN의 프로그래밍 언어 소프트웨어 상을 수상했다.

3. Philosophy

ML 계열 언어인 OCaml은 정적 타입 시스템과 타입 추론 컴파일러로 잘 알려져 있다. 이 언어는 ML과 유사한 타입 시스템 아래에서 함수형 프로그래밍, 명령형 프로그래밍, 객체 지향 프로그래밍 패러다임을 통합한다. 따라서 프로그래머가 OCaml을 사용하기 위해 반드시 순수한 함수형 프로그래밍 패러다임에 익숙해야 할 필요는 없다.

OCaml은 정적 타입 시스템을 통해 프로그래머가 타입 제약 안에서 작업하도록 유도하며, 이는 동적 타입 언어에서 발생할 수 있는 많은 런타임 타입 관련 문제를 방지한다. 또한, OCaml의 타입 추론 컴파일러는 대부분의 정적 타입 언어에서 요구되는 수동 타입 명시의 필요성을 크게 줄여준다. 예를 들어, 변수의 자료형이나 함수의 타입 시그니처는 자바나 C#과 같은 언어처럼 명시적으로 선언할 필요 없이, 코드 내 연산자나 함수 사용 방식으로부터 추론될 수 있다. OCaml의 타입 시스템을 효과적으로 사용하려면 어느 정도의 이해가 필요할 수 있지만, 이는 안정적이고 성능이 우수한 소프트웨어를 개발하는 데 기여한다.

OCaml은 다른 학문적 배경을 가진 언어들과 비교했을 때 성능을 강조한다는 점이 두드러진다. 정적 타입 시스템은 런타임에서의 타입 불일치를 방지하여, 동적 타입 언어의 성능 저하 요인인 런타임 타입 및 안전성 검사를 불필요하게 만든다. 동시에, 배열 경계 검사 해제나 직렬화와 같은 일부 타입 안전하지 않은 기능 사용 경우를 제외하고는 런타임 안전성을 보장한다. 실제로는 이러한 예외적인 경우를 피하는 것이 가능하다.

타입 검사 외에도, 함수형 프로그래밍 언어는 funarg 문제와 같은 이슈로 인해 효율적인 기계어 코드 컴파일이 어려운 경우가 많다. OCaml의 최적화 컴파일러는 표준적인 루프, 레지스터, 명령어 최적화와 더불어 정적 프로그램 분석 기법을 사용하여 값 박싱과 클로저 할당을 최적화한다. 이를 통해 함수형 프로그래밍 구조를 광범위하게 사용하더라도 결과 코드의 성능을 극대화할 수 있다.

자비에 르로이는 "OCaml은 괜찮은 C 컴파일러 성능의 최소 50%를 제공한다"고 언급했지만,[7] 직접적인 비교는 어렵다. OCaml 표준 라이브러리의 일부 함수는 다른 언어 표준 라이브러리의 동일 기능 함수보다 더 빠른 알고리즘으로 구현되기도 한다. 예를 들어, OCaml 표준 라이브러리의 집합 합집합 연산은 집합의 불변성을 활용하여 출력 결과에 입력 집합의 일부를 재사용할 수 있기 때문에, 이론적으로 C++자바와 같은 명령형 언어의 표준 라이브러리 함수보다 점근적으로 더 빠르다(영구적 자료 구조 참조).

OCaml은 ML 스타일의 타입 추론을 일반적인 객체 시스템으로 확장한 점이 특징이다. 이는 구조적 서브타이핑을 가능하게 하여, 객체 타입이 명시적인 상속 관계 없이도 메서드 시그니처가 호환되면 서로 호환되는 것으로 간주한다. 이는 정적 타입 언어에서는 드문 특징이다.

4. Features

ML 계열 언어처럼 정적 타입 시스템과 타입 추론 컴파일러로 잘 알려져 있다. OCaml은 ML과 유사한 타입 시스템 아래에서 함수형 프로그래밍, 명령형 프로그래밍, 객체 지향 프로그래밍을 통합한다. 이로 인해 프로그래머가 OCaml을 사용하기 위해 순수 함수형 패러다임에 깊이 익숙할 필요는 없다.

OCaml은 정적 타입 시스템을 통해 프로그래밍하도록 하여, 동적 타입 언어에서 발생할 수 있는 많은 타입 관련 런타임 오류를 방지한다. 또한, 타입 추론 컴파일러 덕분에 자바나 C#과 같은 언어와 달리 변수 자료형이나 함수 타입 시그니처를 명시적으로 선언해야 하는 경우가 크게 줄어든다. 타입 시스템을 효과적으로 사용하려면 어느 정도의 이해가 필요할 수 있지만, 이는 안정적이고 성능 좋은 소프트웨어 개발로 이어진다.

OCaml은 학문적 배경을 가진 다른 언어들에 비해 성능을 강조하는 점이 특징이다. 정적 타입 시스템은 런타임 타입 불일치를 막아 동적 타입 언어의 성능 저하 요인인 런타임 타입 및 안전성 검사를 불필요하게 만든다. 일부 타입 안전성이 보장되지 않는 기능(배열 경계 검사 해제, 직렬화 등)이 사용될 수 있지만, 실제로는 드물게 사용되므로 피할 수 있다. 타입 검사 외에도, OCaml의 최적화 컴파일러는 정적 프로그램 분석 기법을 사용하여 값 박싱 및 클로저 할당을 최적화하며, 표준 루프, 레지스터, 명령어 최적화를 수행하여 함수형 프로그래밍 구조를 사용하더라도 코드 성능을 극대화한다. 자비에 르로이는 "OCaml은 괜찮은 C 컴파일러 성능의 최소 50%를 제공한다"고 언급한 바 있다.[7] (다만 직접적인 비교는 어렵다.) 일부 표준 라이브러리 함수는 다른 언어보다 빠른 알고리즘으로 구현되기도 한다. 예를 들어, 집합 합집합 연산은 집합의 불변성을 활용하여 입력 집합의 일부를 재사용함으로써 이론적으로 명령형 언어(예: C++, Java)의 구현보다 점근적으로 빠를 수 있다(영구적 자료 구조 참조).

주요 기능은 다음과 같다:


  • 정적 타입 시스템
  • 타입 추론
  • 매개변수 다형성
  • 꼬리 재귀 최적화
  • 패턴 매칭
  • 1급 어휘 클로저
  • 펑터(매개변수화된 모듈)
  • 예외 처리
  • 효과 처리 (OCaml 5.0 이상)
  • 증분 세대 자동 가비지 수집


OCaml은 ML 스타일의 타입 추론을 객체 시스템으로 확장한 점이 특징이다. 구조적 서브타이핑을 지원하여, 객체 타입은 선언된 상속 관계와 무관하게 메서드 시그니처가 호환되면 호환되는 것으로 간주된다. 이는 정적 타입 언어에서는 드문 기능이다.

C 언어와의 상호작용을 위해 외부 함수 인터페이스(FFI)를 제공하며, C 및 포트란과 호환되는 형식의 효율적인 수치 배열을 언어 차원에서 지원한다. 또한, OCaml 함수 라이브러리를 생성하여 C 프로그램에 연결할 수 있어, OCaml 환경이 없는 C 프로그래머에게도 라이브러리 배포가 가능하다.

언어 자체에 내장된 매크로 시스템(메타 프로그래밍)은 없지만, OCaml 플랫폼은 코드 전처리기 작성을 위한 라이브러리를 공식적으로 지원한다. 특히 추상 구문 트리(AST) 수준에서 작동하는 PPX(Pre-Processor eXtension) 방식이 권장된다.

OCaml 배포판에는 다음과 같은 도구들이 포함된다:

  • 어휘 분석기 생성기 (`ocamllex`) 및 파서 생성기 (`ocamlyacc`)
  • 오류 조사를 위해 뒤로 단계별 실행을 지원하는 디버거
  • 문서 생성기
  • 성능 측정을 위한 프로파일러
  • 다양한 범용 라이브러리


네이티브 코드 컴파일러는 유닉스, 마이크로소프트 윈도우, macOS 등 다양한 플랫폼을 지원한다. 주요 아키텍처에 대한 네이티브 코드 생성 지원을 통해 이식성을 확보한다. 지원 아키텍처는 버전에 따라 다음과 같이 변화해왔다:

아키텍처지원 상태
X86-64 (AMD64)OCaml 5.0.0 이상
RISC-VOCaml 5.0.0 이상
ARM64OCaml 5.0.0 이상
IBM ZOCaml 5.0.0 이전, OCaml 5.1.0부터 재지원
PowerOCaml 5.0.0 이전, OCaml 5.2.0부터 재지원 예정
IA-32OCaml 5.0.0 이전
ARMOCaml 5.0.0 이전
SPARCOCaml 4.06.0 이전
DEC 알파, HPPA, IA64, MIPSOCaml 4.00.0 이전



네이티브 코드 생성이 지원되지 않는 경우, 바이트코드 컴파일러를 통해 C 컴파일러가 있는 32비트 또는 64비트 아키텍처에서 실행 가능하다.

OCaml 바이트코드 및 네이티브 코드 프로그램은 선점적 컨텍스트 스위칭을 사용하는 멀티스레딩 스타일로 작성될 수 있다. 동일한 도메인[19]의 OCaml 스레드는 시간 공유를 통해서만 실행된다. 그러나 OCaml 프로그램은 여러 도메인을 포함할 수 있다.

5. Derived languages


  • MetaOCaml[23]: 런타임 중에 새로운 기계어 코드의 점진적인 컴파일을 가능하게 하는 OCaml의 다단계 프로그래밍 확장이다. 다단계 프로그래밍은 런타임에 처리할 데이터에 대한 더 자세한 정보를 활용하여 일반적인 컴파일 시간보다 상당한 속도 향상을 가져올 수 있다. 이를 통해 점진적 컴파일러는 조건 검사 등 많은 경우를 최적화할 수 있다. 예를 들어, 컴파일 시점에는 지수 함수의 밑(`x`)만 알고 지수(`n`)는 런타임에 알게 되는 경우, MetaOCaml을 사용하면 `n` 값이 정해졌을 때 해당 값에 특화된 빠른 지수 함수를 동적으로 생성하고 컴파일할 수 있다.
  • F#: OCaml에 기반을 둔 .NET 프레임워크 언어이다. 마이크로소프트가 주도하는 .NET 생태계 위에서 동작하며 관련 기술 스택과 밀접한 연관을 가진다.
  • JoCaml: 동시성 프로그래밍과 분산 컴퓨팅 프로그램 개발을 위한 기능들을 통합한 언어이다.
  • Reason: 페이스북에서 만든 OCaml의 대안 구문 및 툴체인이다. 네이티브 코드뿐만 아니라 자바스크립트로도 컴파일할 수 있는 특징을 가진다.

6. Software written in OCaml


  • Ahrefs: SEO 소프트웨어 제품
  • Alt-Ergo: SMT 솔버.
  • Astrée: 정적 분석기.
  • Be Sport: 소셜 네트워크.
  • Coccinelle: C 프로그램의 소스 코드를 변환하기 위한 유틸리티.
  • Coq: INRIA에서 개발한 형식 증명 관리 시스템 및 정리 증명 지원 언어.
  • Easycrypt: 컴퓨터 지원 증명 작성 도구.
  • F*: 프로그램 검증을 위한 고급, 다중 패러다임, 함수형 및 객체 지향 프로그래밍 언어.
  • FFTW: 이산 푸리에 변환을 계산하기 위한 라이브러리. 여러 C 루틴은 OCaml 프로그램인 `genfft`로 생성되었다.
  • 페이스북 메신저: 웹 버전.
  • Flow: 페이스북이 제작한 정적 분석기로, 자바스크립트의 정적 타입을 추론하고 검사한다.
  • Frama-C: C 프로그램 분석 프레임워크.
  • GeneWeb: 무료 오픈 소스 다중 플랫폼 족보 소프트웨어.
  • Hack 프로그래밍 언어 컴파일러: 페이스북이 제작했으며, 정적 타입을 사용하여 PHP를 확장한다.
  • Haxe: 오픈 소스 프로그래밍 언어 및 컴파일러.
  • HOL Light: 형식 증명 지원 도구.
  • Infer: 페이스북Java, C, C++, Objective-C용으로 제작한 정적 분석기. iOS 및 Android 앱의 버그를 감지하는 데 사용된다.
  • Liquidsoap: 멀티미디어 스트림을 생성하기 위한 스크립팅 언어.
  • 미디어위키에서 TeX 표기법으로 HTML, MathML, 이미지 수식을 생성하는 프로그램.[41]
  • MirageOS: 순수 OCaml로 작성된 유니커널 프로그래밍 프레임워크.
  • MLdonkey: EDonkey 네트워크를 기반으로 한 P2P 파일 공유 애플리케이션.
  • Ocsigen: 클라이언트 서버 웹 및 모바일 개발 프레임워크.
  • Opa: 웹 개발을 위한 무료 오픈 소스 프로그래밍 언어.
  • Owl Scientific Computing: 과학 및 엔지니어링 컴퓨팅을 위한 전용 시스템.
  • Reason / ReScript: 범용, 고급, 다중 패러다임, 함수형 및 객체 지향 프로그래밍 언어.
  • Rust 컴파일러: 처음에는 OCaml로 구현되었으며 셀프 호스팅되었다.
  • Tezos: XTZ를 기본 통화로 사용하는 자체 수정 스마트 계약 플랫폼.
  • Unison: 두 디렉토리 간의 파일을 동기화하는 파일 동기화 프로그램.
  • WebAssembly: 참조 인터프리터. WebAssembly 내에서 실행하기 위한 저수준 바이트코드이다.
  • Xen Cloud Platform (XCP): Xen 하이퍼바이저를 위한 턴키 가상화 솔루션.

7. Users

적어도 수십 개의 회사에서 OCaml을 어느 정도 사용하고 있다.[29] 주목할 만한 예는 다음과 같다.


  • 블룸버그 L.P.: BuckleScript(OCaml 컴파일러 백엔드, JavaScript를 타겟팅)를 개발했다.[30]
  • 시트릭스 시스템즈: XenServer(2018년에 Citrix Hypervisor로 리브랜딩)에서 OCaml을 사용한다.[31]
  • 페이스북: OCaml로 Flow,[32] Hack, Infer, Pfff, ReasonML을 개발했다.
  • 제인 스트리트 캐피탈: 전산 매매 회사로, 초창기에 OCaml을 선호하는 언어로 채택했으며,[33] 2023년 현재까지 계속 사용하고 있다.[34][35]
  • 도커: macOS 및 윈도우 데스크톱 에디션에서 OCaml을 사용한다.[36][37]


학술 교육 및 연구의 맥락에서 OCaml은 대학교와 칼리지 모두에서 컴퓨터 과학 교육 프로그램에 상당한 존재감을 가지고 있다. 교육 자료 및 이러한 교육 프로그램 목록은 ocaml.org에서 확인할 수 있다.

8. Code examples

OCaml 코드 예제는 OCaml의 기본적인 문법과 특징을 보여준다.


  • 헬로 월드 프로그램

다음은 화면에 "Hello World!"를 출력하는 가장 기본적인 프로그램 `hello.ml`이다.



print_endline "Hello World!"



이 프로그램은 바이트 코드 실행 파일로 컴파일할 수 있다.



$ ocamlc hello.ml -o hello



또는 최적화된 네이티브 코드 실행 파일로 컴파일할 수도 있다.



$ ocamlopt hello.ml -o hello



컴파일된 프로그램은 다음과 같이 실행할 수 있다.



$ ./hello

Hello World!

$



`ocamlc` 명령어에서 첫 번째 인수인 `hello.ml`은 컴파일할 소스 파일을 지정하고, `-o hello` 플래그는 출력 파일 이름을 지정한다.
OCaml 코드는 ''최상위 읽기-평가-출력 루프'' (Read-Eval-Print Loop) 환경에서 대화형으로 실행하며 학습하기 용이하다.[20] OCaml 최상위 환경은 터미널에서 `ocaml` 명령어를 실행하여 시작할 수 있다.



$ ocaml

Objective Caml version 3.09.0

#



`#` 프롬프트 뒤에 코드를 입력하면 OCaml이 해당 코드의 결과와 추론된 타입을 출력한다. 예를 들어, `1 + 2 * 3`을 계산하면 다음과 같다.



# 1 + 2 * 3;;

  • : int = 7



OCaml은 이 표현식의 타입을 `int`(머신 정밀도 정수)로 추론하고 결과값 `7`을 보여준다.
다음은 재귀 함수를 이용하여 피보나치 수를 계산하는 예제이다. 자세한 내용은 하위 섹션에서 다룬다.



let rec fib_aux n a b =

match n with

| 0 -> a

| _ -> fib_aux (n - 1) b (a+b)

let fib n = fib_aux n 0 1


  • 퀵소트 구현

다음은 패턴 매칭을 활용하여 리스트를 정렬하는 퀵소트 알고리즘의 예제이다. 자세한 내용은 하위 섹션에서 다룬다.



let rec qsort = function

| [] -> []

| pivot :: rest ->

let is_less x = x < pivot in

let left, right = List.partition is_less rest in

qsort left @ [pivot] @ qsort right



OCaml은 ML 계열 언어의 특징을 가지며, 타입 추론 기능 덕분에 대부분의 경우 명시적인 타입 선언 없이 코드를 작성할 수 있어 간결하다. 다만, Standard ML 등 기존 ML 언어와는 표기법, 연산자, 일부 함수의 이름 등에서 차이가 있어 코드를 그대로 사용하기 어려울 수 있다.

8. 1. Option

OCaml의 `option` 타입 생성자는 Haskell의 `Maybe` 타입과 유사하게 주어진 데이터 타입을 보완하여 주어진 데이터 타입의 `Some` 값을 반환하거나 `None`을 반환한다.[22] 이는 값이 존재할 수도 있고 존재하지 않을 수도 있음을 표현하는 데 사용된다.



# Some 42;;

  • : int option = Some 42

# None;;

  • : 'a option = None



다음은 옵션에서 int를 추출하여, int가 존재한다면 문자열로 변환하고, 그렇지 않다면 빈 문자열을 반환하는 함수의 예시이다:



let extract o =

match o with

| Some i -> string_of_int i

| None -> "";;





# extract (Some 42);;

  • : string = "42"

# extract None;;

  • : string = ""


8. 2. Summing a list of integers

리스트는 OCaml의 기본적인 데이터 유형 중 하나이다. 다음 코드는 정수 리스트를 인수로 받아 그 합계를 계산하는 재귀 함수 `sum`을 정의하는 예시이다. 함수 정의에 사용된 `rec` 키워드는 해당 함수가 재귀적임을 나타낸다. 이 함수는 입력받은 정수 리스트를 재귀적으로 순회하며 모든 요소의 합을 구한다. `match` 표현식은 리스트의 상태(비어 있는지 아닌지)에 따라 다른 동작을 수행하게 하는데, 이는 C 언어의 switch 구문과 유사하지만 훨씬 더 일반적인 패턴 매칭 기능이다.



let rec sum integers = (* rec 키워드는 '재귀적'이라는 의미이다. *)

match integers with

| [] -> 0 (* 만약 integers가 빈 리스트 [] 이면, 0을 반환한다. *)

| first :: rest -> first + sum rest (* 만약 integers가 비어있지 않다면, 리스트의 첫 번째 요소(first)와 나머지 리스트(rest)로 분리한 뒤,

first 값과 나머지 리스트(rest)에 대한 재귀 호출 결과를 더한다. rest는 빈 리스트일 수도 있다. *)



위 함수를 사용하여 정수 리스트 `[1; 2; 3; 4; 5]`의 합을 구하는 예시는 다음과 같다.



# sum [1;2;3;4;5];;

  • : int = 15



리스트의 합을 구하는 또 다른 방법은 표준 라이브러리에서 제공하는 fold 함수를 이용하는 것이다. 특히 `List.fold_left` 함수는 리스트의 각 요소를 순회하며 주어진 연산을 누적 적용하는 데 사용된다.



let sum integers =

List.fold_left (fun accumulator x -> accumulator + x) 0 integers

(* (fun accumulator x -> accumulator + x)는 두 정수를 받아 합을 반환하는 익명 함수이다.

0은 누산기(accumulator)의 초기값이다.

integers는 처리할 리스트이다. *)



이 함수 역시 동일한 결과를 반환한다.



# sum [1;2;3;4;5];;

  • : int = 15



위 코드에서 사용된 익명 함수는 단순히 `+` 연산자를 적용하는 것이므로, 다음과 같이 더 간결하게 작성할 수 있다.



let sum integers =

List.fold_left (+) 0 integers (* (+)는 덧셈 연산자 자체를 함수로 사용하는 표현이다. *)



더 나아가, OCaml의 부분 적용 기능을 활용하면 리스트 인수를 생략하여 `sum` 함수 자체를 `List.fold_left (+) 0`의 결과로 정의할 수도 있다. 이렇게 정의된 `sum` 함수는 정수 리스트를 인수로 받아 합계를 계산하는 함수가 된다.



let sum =

List.fold_left (+) 0


8. 3. 퀵소트

OCaml은 재귀 알고리즘을 간결하게 표현하는 데 적합하다. 다음 코드 예제는 리스트를 오름차순으로 정렬하는 퀵 정렬 알고리즘을 패턴 매칭을 사용하여 구현한 것이다.



let rec qsort = function

| [] -> []

| pivot :: rest ->

let is_less x = x < pivot in

let left, right = List.partition is_less rest in

qsort left @ [pivot] @ qsort right



위 코드에서 `function` 키워드와 `|`는 패턴 매칭을 나타낸다. 빈 리스트(`[]`)인 경우 빈 리스트를 반환하고, 그렇지 않은 경우 리스트의 첫 번째 요소(`pivot`)와 나머지(`rest`)를 분리한다. `List.partition` 함수는 `rest` 리스트를 `pivot`보다 작은 요소들의 리스트(`left`)와 크거나 같은 요소들의 리스트(`right`)로 나눈다. 마지막으로 `left`와 `right` 리스트를 각각 재귀적으로 정렬한 후 `pivot`을 중간에 넣어 전체 리스트를 합친다.

OCaml과 같은 ML 계열 언어는 많은 함수형 프로그래밍 언어처럼 재귀 처리에 강점을 보이며, 하스켈 등 다른 함수형 언어에서도 볼 수 있는 패턴 매칭 기능을 효과적으로 활용한다.

비교 연산자인 `>=`의 부분 적용을 사용하여 코드를 더 간결하게 작성할 수도 있다.



let rec qsort = function

| [] -> []

| pivot :: rest ->

let is_less = (>=) pivot in (* x >= pivot 와 동일 *)

let left, right = List.partition is_less rest in

qsort left @ [pivot] @ qsort right


8. 4. Birthday problem

다음 프로그램은 생일 문제를 푸는 예시로, 임의의 집단에서 최소 몇 명이 모여야 생일이 같은 사람이 있을 확률이 50%를 넘는지 계산한다. 모든 사람의 생일이 다를 확률은 1명일 때 1 (또는 100%), 2명일 때 364/365, 3명일 때 364/365 × 363/365 와 같이 점차 감소한다. 이 확률이 0.5 미만이 되는, 즉 생일이 같은 사람이 있을 확률이 50% 이상이 되는 최소 인원수를 구하는 것이다.



let year_size = 365.

let rec birthday_paradox prob people =

let prob = (year_size -. float people) /. year_size *. prob in

if prob < 0.5 then

Printf.printf "answer = %d\n" (people+1)

else

birthday_paradox prob (people+1)

;;

birthday_paradox 1.0 1



위 OCaml 코드는 이 문제를 계산하며, 실행 결과는 23이다. 이는 23명 이상이 모이면 그중에 생일이 같은 사람이 있을 확률이 50%를 넘는다는 것을 의미한다.

8. 5. Church numerals

다음 코드는 처치 인코딩을 사용하여 자연수를 정의하며, 후임자(`succ`)와 덧셈(`add`) 연산을 제공한다. 처치 숫자 `n`은 함수 `f`와 값 `x`를 인자로 받아, `f`를 `x`에 정확히 `n`번 적용하는 고차 함수이다.

아래는 처치 숫자를 문자열로 변환하는 예시이다. 처치 숫자를 함수형 값에서 문자열로 변환하기 위해, 입력 문자열 앞에 문자열 `"S"`를 붙이는 함수와 상수 문자열 `"0"`을 전달한다.



let zero f x = x

let succ n f x = f (n f x)

let one = succ zero

let two = succ (succ zero)

let add n1 n2 f x = n1 f (n2 f x)

let to_string n = n (fun k -> "S" ^ k) "0"

let _ = to_string (add (succ two) two) (* 결과: "S(S(S(S(0))))" *)



다음은 람다 계산 교과서 등에서 볼 수 있는 자연수의 처치 인코딩 코드 예시로, 처치 숫자를 정수로 변환하는 방법을 보여준다.



let zero f x = x

let succ n f x = f (n f x)

let one = succ zero

let two = succ (succ zero)

let add n1 n2 f x = n1 f (n2 f x)

let to_int n = n (fun k -> k + 1) 0

let _ = to_int (add (succ two) two) (* 결과: 4 *)



처치 숫자 `n`을 자연수 `n`으로 변환하려면, 처치 수(실제로는 함수)에 증가시키는 함수(`fun k -> k + 1`)와 초기값 `0`을 전달하면 된다. OCaml과 같은 ML 계열 함수형 언어는 이러한 수학적인 프로그래밍 이론을 코드로 직접 기술할 수 있는 특징이 있다.

8. 6. Arbitrary-precision factorial function (libraries)

OCaml에서는 다양한 라이브러리를 직접 사용할 수 있다. 예를 들어, OCaml에는 임의 정밀도 산술을 위한 내장 라이브러리가 있다. 팩토리얼 함수는 계산 결과값이 매우 빠르게 증가하여, 일반적인 기계 정밀도 숫자(주로 32비트 또는 64비트)의 표현 범위를 금방 넘어서게 된다. 따라서 팩토리얼은 임의 정밀도 산술을 사용하기에 적합한 예시이다.

OCaml의 Num 모듈(현재는 ZArith 모듈로 대체됨)은 임의 정밀도 산술 기능을 제공한다. 이 모듈은 다음 명령어를 사용하여 실행 중인 최상위 수준(top-level) 환경으로 불러올 수 있다.



# #use "topfind";;

# #require "num";;

# open Num;;



Num 모듈을 불러온 후에는 임의 정밀도 숫자 연산자인 `=/`, `*/`, `-/`를 사용하여 팩토리얼 함수를 작성할 수 있다.



# let rec fact n =

if n =/ Int 0 then Int 1 else n */ fact(n -/ Int 1);;

val fact : Num.num -> Num.num =



이 함수를 사용하면 120!처럼 매우 큰 팩토리얼 값도 계산할 수 있다.



# string_of_num (fact (Int 120));;

  • : string =

"6689502913449127057588118054090372586752746333138029810295671352301633557244962989366874165271984981308157637893214090552534408589408121859898481114389650005964960521256960000000000000000000000000000"


8. 7. Triangle (graphics)

다음은 OpenGL을 이용하여 2차원 평면에서 회전하는 삼각형을 그리는 OCaml 프로그램 예제이다.



let () =

ignore (Glut.init Sys.argv);

Glut.initDisplayMode ~double_buffer:true ();

ignore (Glut.createWindow ~title:"OpenGL Demo");

let angle t = 10. *. t *. t in

let render () =

GlClear.clear [ `color ];

GlMat.load_identity ();

GlMat.rotate ~angle:(angle (Sys.time ())) ~z:1. ();

GlDraw.begins `triangles;

List.iter GlDraw.vertex2 [-1., -1.; 0., 1.; 1., -1.];

GlDraw.ends ();

Glut.swapBuffers ()

in

GlMat.mode `modelview;

Glut.displayFunc ~cb:render;

Glut.idleFunc ~cb:(Some Glut.postRedisplay);

Glut.mainLoop ()



이 코드를 실행하기 위해서는 OpenGL에 대한 LablGL 바인딩이 필요하다. 코드를 컴파일하는 방법은 다음과 같다.

  • 바이트코드 컴파일:



$ ocamlc -I +lablGL lablglut.cma lablgl.cma simple.ml -o simple


  • 네이티브 코드 컴파일:



$ ocamlopt -I +lablGL lablglut.cmxa lablgl.cmxa simple.ml -o simple


  • ocamlfind 사용:



$ ocamlfind opt simple.ml -package lablgl.glut -linkpkg -o simple



컴파일 후 생성된 실행 파일을 실행하면 된다.



$ ./simple



OCaml을 사용하면 이보다 훨씬 정교하고 성능이 뛰어난 2D 및 3D 그래픽 프로그램을 개발할 수 있다. OpenGL과 OCaml을 함께 사용하면 작성된 프로그램을 여러 주요 운영체제에서 별다른 수정 없이 컴파일하여 사용할 수 있다는 장점이 있다.

8. 8. Fibonacci sequence

다음 코드는 입력된 숫자 n의 피보나치 수열을 계산한다. 이는 꼬리 재귀패턴 매칭을 사용한다.



let fib n =

let rec fib_aux m a b =

match m with

| 0 -> a

| _ -> fib_aux (m - 1) b (a + b)

in fib_aux n 0 1


8. 9. Higher-order functions

함수는 다른 함수를 입력으로 받거나 결과를 함수로 반환할 수 있는데, 이를 고차 함수(Higher-order function)라고 한다. 예를 들어, 함수 `twice`는 함수 `f`를 입력받아, 주어진 인수에 `f`를 두 번 적용하는 새로운 함수를 생성한다.



(* 함수 f를 받아, x에 f를 두 번 적용하는 함수를 반환 *)

let twice (f : 'a -> 'a) = fun (x : 'a) -> f (f x);;

(* 정수형 함수 예시 *)

let inc (x : int) : int = x + 1;;

let add2 = twice inc;; (* inc 함수를 두 번 적용하는 함수 생성 *)

(* 문자열 함수 예시 *)

let inc_str (x : string) : string = x ^ " " ^ x;;

let add_str = twice(inc_str);; (* inc_str 함수를 두 번 적용하는 함수 생성 *)



위 코드의 실행 결과는 다음과 같다. `add2`는 98에 `inc` 함수(1 증가)를 두 번 적용하여 100을 반환하고, `add_str`은 "Test" 문자열에 `inc_str` 함수(문자열 반복 및 공백 추가)를 두 번 적용한다.



# add2 98;;

  • : int = 100

# add_str "Test";;

  • : string = "Test Test Test Test"



`twice` 함수의 정의에서 사용된 타입 변수 `'a`는 이 함수가 특정 타입(예: `int -> int`)의 함수뿐만 아니라, `타입 'a`에서 자기 자신으로 매핑되는 모든 종류의 함수 `f`에 적용될 수 있음을 나타낸다. 즉, 다형성을 지원한다.

고차 함수는 자기 자신에게도 적용될 수 있다. 예를 들어, `twice` 함수에 `twice` 함수를 적용하여, 인자로 받은 함수를 네 번 적용하는 `fourtimes` 함수를 만들 수 있다.



# let fourtimes f = (twice twice) f;;

val fourtimes : ('a -> 'a) -> 'a -> 'a =

# let add4 = fourtimes inc;; (* inc 함수를 네 번 적용하는 함수 생성 *)

val add4 : int -> int =

# add4 98;;

  • : int = 102


참조

[1] 웹사이트 Modules https://ocaml.org/le[...] 2020-02-22
[2] 웹사이트 Objective Caml 1.00 https://sympa.inria.[...] caml-list mailing list
[3] 웹사이트 Influences - The Rust Reference https://doc.rust-lan[...] 2023-12-31
[4] 웹사이트 Jérôme Vouillon https://www.irif.fr/[...] 2024-06-14
[5] 웹사이트 Didier Remy https://pauillac.inr[...] 2024-06-14
[6] 웹사이트 A History of OCaml http://ocaml.org/lea[...] 2016-12-24
[7] 뉴스 Linux Weekly News https://lwn.net/Arti[...]
[8] 웹사이트 A J Milner - A.M. Turing Award Laureate https://amturing.acm[...] 2022-10-06
[9] 웹사이트 1.2. OCaml: Functional Programming in OCaml https://courses.cs.c[...] 2022-10-06
[10] 웹사이트 Prologue - Real World OCaml https://dev.realworl[...] 2022-10-06
[11] 웹사이트 A History of OCaml – OCaml https://v2.ocaml.org[...] 2022-10-07
[12] 웹사이트 Release of OCaml 5.0.0 OCaml Package https://ocaml.org/ne[...] 2022-12-16
[13] 웹사이트 Projet Cristal http://cristal.inria[...] 2022-10-07
[14] 웹사이트 Gallium team - Home http://gallium.inria[...] 2022-10-07
[15] 웹사이트 Home http://cambium.inria[...] 2022-10-07
[16] 웹사이트 OCaml compiler governance and membership https://ocaml.org/go[...]
[17] 웹사이트 OCaml governance and projects https://ocaml.org/go[...]
[18] 웹사이트 ocaml/asmcomp at trunk · ocaml/ocaml · GitHub https://github.com/o[...] 2015-05-02
[19] 문서
[20] 웹사이트 OCaml - The toplevel system or REPL (ocaml) https://ocaml.org/ma[...] 2021-05-17
[21] 웹사이트 OCaml - Batch compilation (Ocamlc) https://caml.inria.f[...]
[22] 웹사이트 3.7. Options — OCaml Programming: Correct + Efficient + Beautiful https://cs3110.githu[...] 2022-10-07
[23] 웹사이트 BER MetaOCaml http://okmij.org/ftp[...]
[24] 간행물 EasyCrypt/easycrypt https://github.com/E[...] EasyCrypt 2024-07-05
[25] 웹사이트 Messenger.com Now 50% Converted to Reason · Reason https://reasonml.git[...] 2018-02-27
[26] 웹사이트 Flow: A Static Type Checker for JavaScript https://flow.org/en/ 2019-02-10
[27] 웹사이트 Infer static analyzer https://fbinfer.com/
[28] 웹사이트 WebAssembly/spec: WebAssembly specification, reference interpreter, and test suite. https://github.com/W[...] World Wide Web Consortium 2021-05-14
[29] 웹사이트 Companies using OCaml https://ocaml.org/le[...] OCaml.org 2021-05-14
[30] 웹사이트 BuckleScript: The 1.0 release has arrived! {{!}} Tech at Bloomberg https://www.techatbl[...] 2017-05-21
[31] 간행물 Using functional programming within an industrial product group: perspectives and perceptions https://dl.acm.org/d[...] Association for Computing Machinery
[32] 웹사이트 Flow on GitHub https://github.com/f[...]
[33] 웹사이트 OCaml for the Masses http://cacm.acm.org/[...] 2015-05-02
[34] 웹사이트 Keynote - Observations of a Functional Programmer http://cufp.org/2016[...] Association for Computing Machinery|ACM Commercial Uses of Functional Programming
[35] 팟캐스트 Signals & Threads https://signalsandth[...] Jane Street Capital
[36] 웹사이트 Improving Docker with Unikernels: Introducing HyperKit, VPNKit and DataKit https://www.docker.c[...] Docker, Inc.
[37] 웹사이트 VPNKit on GitHub https://github.com/m[...]
[38] 웹사이트 https://caml.inria.f[...]
[39] 문서
[40] 서적 『入門OCaml』 毎日コミュニケーションズ
[41] MediaWiki Texvc - MediaWiki https://www.mediawik[...]
[42] 문서
[43] 웹사이트 https://mzp.hatenabl[...]
[44] 웹사이트 http://mldonkey.sour[...]
[45] 웹사이트 http://cristal.inria[...]
[46] 웹사이트 https://frama-c.com/
[47] 웹사이트 https://flow.org/
[48] 웹사이트 https://fbinfer.com/



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com