하스켈의 특징

Haskell features

이 기사는 하스켈의 특징을 설명한다.

요인

기능 언어의 구문을 입증하는 데 자주 사용되는 간단한 예는 Haskell에 표시된 비 음의 정수에 대한 요인 함수다.

요인의 :: 정수 -> 정수 요인의 0 = 1 요인의 n = n * 요인의 (n-1) 

또는 한 줄에:

요인의 n = 만일 n > 1 그때 n * 요인의 (n-1) 다른 1 

이것은 하나의 종단 베이스 케이스가 있는 재귀 함수로 그 요인을 설명한다. 수학 교과서에서 발견되는 요인 설명과 비슷하다. 하스켈 코드의 대부분은 시설과 구문에서의 표준 수학 표기법과 유사하다.

요인 함수의 첫 번째 선은 이 함수의 유형을 설명하며, 선택 사항이지만 포함시키는 것이 좋은 스타일로[1] 간주된다. 함수 요인(으)로 읽을 수 있다.factorial)에는 유형이 있음(::)에서 정수로 (Integer -> Integer즉, 인수로 정수를 취하고, 또 다른 정수를 반환한다. 프로그래머가 유형 주석을 제공하지 않은 경우 정의의 유형은 자동으로 유추된다.

두 번째 라인은 해스켈의 중요한 특징인 패턴 매칭에 의존한다. 함수의 매개변수는 괄호 안에 있지 않고 공백으로 구분되어 있다는 점에 유의하십시오. 함수의 인수가 0이면 정수 1(1)을 반환한다. 다른 모든 경우에 대해 세 번째 라인이 시도된다. 이것은 재귀이며, 베이스 케이스에 도달할 때까지 기능을 다시 실행한다.

사용 product 프루트에서 나오는 함수, C표준 라이브러리와 유사한 다수의 작은 함수, 그리고 산술 시퀀스에 대해 하스켈 구문을 사용하여 다음과 같이 요인 함수를 하스켈로 표현할 수 있다.

요인의 n = 상품 [1..n] 

여기 [1..n] 목록 형식에서 산술 순서 1, 2, …, n을 나타낸다. Predefront 함수 사용 enumFromTo, 표현 [1..n] 라고 쓸 수 있다. enumFromTo 1 n, 요인 함수를 다음과 같이 표현할 수 있음

요인의 n = 상품 (EnumFrom에게 1 n) 

즉, 함수 합성 연산자(Haskell에서 점으로 표현)를 사용하여 큐레이션된 열거 함수로 제품 함수를 구성하면 포인트 프리 스타일로 다시 작성할 수 있다.[2]

요인의 = 상품 . EnumFrom에게 1 

허그스 통역사에서는 흔히 기능을 정의하고 a로 분리된 동일 선에 사용해야 한다. where 또는 let..in. 예를 들어 위의 예를 테스트하고 출력을 보려면 120:

하게 하다 { 요인의 n   n > 0 = n * 요인의 (n-1); 요인의 _ = 1 }  요인의 5 

또는

요인의 5 어디에 요인의 = 상품 . EnumFrom에게 1 

GHCi 통역기에는 이러한 제한이 없으며 기능 정의는 (이러한 항목으로) 한 줄에 입력할 수 있다. let 이 없는 구문 in 부품) 및 나중에 참조한다.

더 복잡한 예

계산기.

바로 아래의 하스켈 소스에서 "::"는 "has type"으로 읽을 수 있고, "a —> b"는 "a에서 b까지의 함수"로 읽을 수 있다.(하스켈 "calc : String —> [Flat]은 "로 읽을 수 있다.calc 문자열에서 "플로트 목록"에 이르는 함수 유형을 가지고 있다.) 두 번째 줄에서 "계산 = ... " 등호 부호는 "될 수 있다"로 읽을 수 있으며, 따라서 "계산 = ..."가 있는 여러 개의 행이 있다. "는 가능한 여러 값으로 읽을 수 있다. calc, 각 행에 상세히 기술된 상황에 따라.

고차 함수로 표현된 간단한 역 폴란드어 표기법 계산기 foldl 패턴 매칭classRead 유형을 사용하는 에 f 인수가 정의된 경우:

계산하다 ::  -> [플로트] 계산하다 = 접다 f [] . 단어   어디에      f (x:y:zs) "+" = (y + x):zs     f (x:y:zs) "-" = (y - x):zs     f (x:y:zs) "*" = (y * x):zs     f (x:y:zs) "/" = (y / x):zs     f (x:y:zs) "FLIP" =  y:x:zs     f xs y = 읽다 y : xs 

빈 리스트는 초기 상태로서 f는 한 번에 한 단어를 함수 이름으로 해석하여 리스트의 머리에서 두 개의 숫자를 취하여 결과를 다시 밀어 넣거나, 단어를 부동 소수점 숫자로 구문 분석하여 리스트에 미리 입력한다.

피보나치 수열

다음 정의는 피보나치 숫자의 목록을 선형 시간으로 생성한다.

섬유질 = 0 : 1 : zipWith (+) 섬유질 (꼬리를 치다 섬유질) 

무한 목록은 코어커서에 의해 생성되며, 목록의 후자 값은 초기 두 항목 0과 1부터 시작하여 필요에 따라 계산된다. 이런 종류의 정의는 해스켈 프로그래밍의 중요한 특징인 게으른 평가에 의존한다. 평가가 어떻게 진화하는지 예를 들면, 다음은 6개 항목의 계산 후 섬유와 꼬리 섬유 값을 보여주고, zipWith (+)가 4개의 항목을 어떻게 생산하고 다음 항목을 어떻게 생산해 나가는지를 보여준다.

섬유 = 0 : 1 : 2 : 3 : 5 : ... + + + + + + 꼬리 섬유 = 1 : 2 : 3 : 5 : ...                = = = = = zipWith...  = 1 : 2 : 3 : 5 : 8 : ... 섬유 = 0 : 1 : 1 : 2 : 3 : 8 : ...  

GHC의 병렬 목록 이해 구문(GHC 확장은 특수 명령줄 플래그, 여기서 -XParalListComp 또는 소스 파일을 사용하여 활성화해야 함)을 사용하여 작성된 동일한 기능 {-# LANGUAGE ParallelListComp #-}):

섬유질 = 0 : 1 : [ a+b   a <- 섬유질   b <- 꼬리를 치다 섬유질 ] 

또는 정기적인 목록 포함:

섬유질 = 0 : 1 : [ a+b   (a,b) <- 지퍼를 채우다 섬유질 (꼬리를 치다 섬유질) ] 

또는 직접 자가 분석:

섬유질 = 0 : 1 : 다음에 섬유질 어디에 다음에 (a : t@(b:_)) = (a+b) : 다음에 t 

상태 저장 생성 기능 포함:

섬유질 = 다음에 (0,1) 어디에 다음에 (a,b) = a : 다음에 (b, a+b) 

또는 을 가지고 unfoldr:

섬유질 = 펼치다 (\(a,b) -> 그냥 (a, (b, a+b))) (0, 1) 

또는 scanl:

섬유질 = 0 : 샅샅이 뒤지다 (+) 1 섬유질 

Haskell의 사전 정의된 고정점 결합기에 데이터 재귀 사용:

섬유질 = 고치다 (\xs -> 0 : 1 : zipWith (+) xs (꼬리를 치다 xs))   -- zipWith 버전      = 고치다 ((0:) . (1:) . (zipWith (+) <*> 꼬리를 치다))      -- 위와 같은, 포인트 프리      = 고치다 ((0:) . 샅샅이 뒤지다 (+) 1)                        -- scanl 버전 

요인

앞에서 살펴본 요인은 함수 시퀀스로 다음과 같이 기록할 수 있다.

요인의 n = 접다 ((.) . (*)) id [1..n] $ 1 -- 요인 5 == (1*) ((2*) (3*) (4) (4*) ( (5*) ID )) 1) 1) 1) 1 -- == (1*) . (2*) . (3*) . (4*) . (5*) id $1 -- == 1* ( 2* ( 3* ( 4* ( 5* (ID 1 ))))  요인의 n = 접다 ((.) . (*)) (경시하다 1) [1..n] $ () -- 요인 5 == (1*) ((2*) (3*) (4*) (5*) (5*) (1 )) ())) () -- == (1*) . (2*) . (3*) . (4*) . (5*) . constance 1 달러 () -- == 1* ( 2* ( 4* ( 5* (경구 1) )))))  요인의 n = 접다 (($) . (*)) 1 [1..n] = 접다 ($) 1 $ 지도를 그리다 (*) [1..n] --요인 5 == (1*) ((2*) 달러 (3*) 달러 (4) 달러 (4*) ( (5*) 1 )))) --             == (1*) $ (2*) $ (3*) $ (4*) $ (5*) $ 1 --             ==  1*  (  2*  (  3*  (  4*  (  5*    1 )))) 

더 많은 예

해밍 수

해밍 번호 목록을 순서대로 반환하는 매우 간결한 함수:

해밍 = 1 : 지도를 그리다 (2*) 해밍 `결합하다` 지도를 그리다 (3*) 해밍                                   `결합하다` 지도를 그리다 (5*) 해밍 

다양한 것 처럼 fibs 위에 표시된 해결책은 1의 기본 사례에서 시작하여 목록의 앞 부분을 기반으로 새로운 항목을 작성하는 주문형 번호 목록을 작성하기 위해 코어커서를 사용한다.

여기 함수 union 그것을 뒷면에 동봉하여 운영자로 사용된다. 그것들 case 절은 두 개의 오름차순 리스트를 중복 항목 없이 하나의 오름차순 리스트로 병합하는 방법을 정의하며, 집합은 순서 리스트로 나타낸다. 그것의 동반 기능 minus 설정 차이 구현:

결합하다 (x:xs) (y:ys) = 케이스 비교하다 x y      LT -> x : 결합하다  xs (y:ys)       EQ -> x : 결합하다  xs    ys       GT -> y : 결합하다 (x:xs) ys   결합하다  xs  []  = xs   결합하다  []  ys  = ys 
빼다 (x:xs) (y:ys) = 케이스 비교하다 x y       LT -> x : 빼다  xs (y:ys)     EQ ->     빼다  xs    ys      GT ->     빼다 (x:xs) ys 빼다  xs  _  = xs -- 

보다 효율적인 운영을 위해 고유한 배수만 생성할 수 있다. 중복 항목이 없으므로 제거할 필요가 없음:

평활하게 하다 = 1 : 접다 (\p s -> 고치다 $ 병합 기준 (<) s . 지도를 그리다 (p*) . (1:)) [] [2,3,5]   어디에     고치다 f = x  어디에 x = f x         -- 고정점 결합기(공유 포함) 

이것은 더 효율적인 기능을 사용한다. merge 중복되는 부분(다음 기능에도 사용됨)과는 무관하게, mergesort ):

병합 기준 덜하다 xs ys = 합병하다 xs ys  어디에   합병하다  xs     []  = xs    합병하다  []     ys  = ys   합병하다 (x:xs) (y:ys)   덜하다 y x  = y : 합병하다 (x:xs) ys                         그렇지 않으면 = x : 합병하다 xs (y:ys) 

각 세로 막대( )는 가드 표현으로 가드 조를 시작하며, 앞에 가드 표현 = 부호 및 부호 뒤에 해당하는 정의는 가드가 참일 경우 평가된다.

메르세데스포르트

다음은 고차 함수를 사용하여 정의된 상향 병합 정렬 until:

mergesortBy 덜하다 [] = [] mergesortBy 덜하다 xs = 머리 $       까지 (무효의 . 꼬리를 치다) (쌍쌍으로 $ 병합 기준 덜하다) [[x]   x <- xs]  쌍쌍으로 f (a:b:t) = f a b : 쌍쌍으로 f t 쌍쌍으로 f      t  = t 

소수

프라임의 수학적 정의는 하스켈로 거의 단어로 번역될 수 있다.

- "1보다 작은 정수로 나눌 수 없는 1보다 큰 정수" 프라임즈 = [ n   n <- [2..], 전부 ((> 0) .  n) [2..(n-1)] ] 

이것은 재판부별로 소수점을 찾아낸다. 효율성에 최적화되어 있지 않고 성능이 매우 좋지 않다는 점에 유의하십시오. 조금 더 빠른 것은 (그러나 여전히 매우 느린)[3] 데이비드 터너의 이 암호다.

프라임즈 = 체에 밭다 [2..]  어디에           체에 밭다 (p:xs) = p : 체에 밭다 [x   x <- xs,  x p /= 0] 

훨씬 더 빠른 것은 최적의 시험 분할 알고리즘이다.

프라임즈 = 2 : [ n   n <- [3..], 전부 ((> 0) .  n) $                       시간이 걸리다 ((<= n) . (^2)) 프라임즈] 

또는 에라토스테네스의 무제한 체에다가, 단계적으로 체를 미룬다.[4]

프라임즈 = 2 : 체에 밭다 프라임즈 [3..]  어디에              체에 밭다 (p:ps) (스판하다 (< p*p) -> (h, t)) =                     h ++ 체에 밭다 ps (빼다 t [p*p, p*p+p..]) 

아니면 리처드 버드의 체를 합쳐서 [5]시행하거나

- "합성된 숫자가 없는 1 이상의 정수는 - 각 프라임의 배수를 열거하여 발견된다." 프라임즈 = 2 : 빼다 [3..]                (접다 (\(m:ms) r -> m : 결합하다 ms r) []                        [[p*p, p*p+p ..]   p <- 프라임즈]) 

또는 거의 최적(목록 기반 코드의 경우) 시간 복잡성과 매우 낮은 공간 복잡성을 갖는 훨씬 더 빠른 트리 형태의 접이식 변종[6](rest-based code)으로, 다단계 재귀적 프라임 생산을 통해 달성된 공간 복잡성:

프라임즈 = 2 : _Y ((3 :) . 빼다 [5,7..] . _U                         . 지도를 그리다 (\p -> [p*p, p*p+2*p..]))   어디에     -- 공유되지 않는 Y 결합기:     _Y g = g (_Y g)     - (g (g (g (...)))))     -- 큰 유니온 ~=nub.nub.cnu.snu.l     _U ((x:xs):t) = x : (결합하다 xs . _U . 쌍쌍으로 결합하다) t 

연속된 사각형 사이의 세그먼트별로 배열 작업을 수행하면

수입하다 데이터.어레이 수입하다 Data.List (꼬리들, 이음매)  프라임즈 = 2 : [ n      (r:q:_, px를 붙이다) <- 지퍼를 채우다 (꼬리들 (2 : [p^2   p <- 프라임즈]))                       (이음매 프라임즈),    (n,진실의)    <- 연상시키다 (축열 어레이 (\_ _ -> 거짓의) 진실의                      (r+1,q-1)                      [ (m,())   p <- px를 붙이다                               , s <- [칸막이하다 (r+p) p*p]                               , m <- [s,s+p..q-1]  ])] 

가능한 가장 짧은 코드는 아마도 nubBy (((>1) .) . gcd) [2..]그것은 꽤 느리다.

구문

배치

Haskell은 새로운 선언의 시작을 나타내기 위해 들여쓰기를 허용한다. 예를 들어, where 절에서:

상품 xs = 으르렁찌렁 찌르다 xs 1   어디에     으르렁찌렁 찌르다 []     a = a     으르렁찌렁 찌르다 (x:xs) a = 으르렁찌렁 찌르다 xs (a*x) 

내포함수에 대한 두 방정식 prod 수직으로 정렬되어 있어 반자동 분리기를 생략할 수 있다. Haskell에서 들여쓰기는 다음과 같은 여러 통사적 구성에서 사용될 수 있다. do, let, case, class그리고 instance.

프로그램 구조를 나타내기 위한 들여쓰기의 사용은 오프사이드 룰이라고 불리던 랜딘ISWIM 언어에서 유래한다. 이것은 나중에 미란다에 의해 채택되었고, 하스켈은 "레이아웃"이라고 불리는 미란다의 오프사이드 규칙의 유사(그러나 오히려 더 복잡한) 버전을 채택했다. 공백에 민감한 구문을 채택하기 위한 다른 언어로는 PythonF#가 있다.

하스켈에서의 레이아웃 사용은 선택사항이다. 예를 들어, 함수 product 위에도 다음과 같이 쓸 수 있다.

상품 xs = 으르렁찌렁 찌르다 xs 1   어디에 { 으르렁찌렁 찌르다 [] a = a; 으르렁찌렁 찌르다 (x:xs) a = 으르렁찌렁 찌르다 xs (a*x) } 

다음 뒤에 있는 명시적 개방 가새 where 키워드는 프로그래머가 명시적 세미콜론을 사용하여 선언문을 분리하기로 선택했으며 선언 리스트는 명시적 마감 버팀대에 의해 종료됨을 나타낸다. 명시적 구분 기호에 대한 지원을 원하는 이유 중 하나는 Haskell 소스 코드의 자동 생성을 더 쉽게 하기 때문이다.

하스켈의 배치 규칙은 복잡하다는 비판을 받아왔다. 특히 이 정의는 파서(parser)가 레이아웃 단면 처리 중 파서(parse) 오류가 발생하면 근접 가새("파서 오류" 규칙)를 삽입해봐야 한다고 명시하고 있다. 전통적인 구문 분석/독소 분석 조합에서 이 규칙을 구현하려면 파서와 어휘 분석기 사이의 양방향 협력이 필요한 반면, 대부분의 언어에서는 이 두 단계를 독립적으로 고려할 수 있다.

함수 호출

함수 적용 f 값어치가 있는 x 단순하게 표현되다 f x.

Haskell은 함수 호출을 infix 연산자와 구문론적으로 구분하지만 의미론적으로는 구별하지 않는다. 문장 부호 문자로 구성된 함수 이름은 백틱으로 둘러싸인 경우 다른 함수 이름처럼 연산자로 사용할 수 있으며 괄호로 둘러싸인 경우 접두사 표기법으로 연산자를 사용할 수 있다.

이 예는 기능을 다음과 같이 부를 수 있는 방법을 보여준다.

  덧셈을 a b = a + b    십1년 = 5 + 5   102년 = (+) 5 5   103년 = 덧셈을 5 5   104년 = 5 `덧셈을` 5 

여러 파라미터를 취하는 것으로 정의되는 기능은 항상 부분적으로 적용할 수 있다. 이항 연산자는 단면 표기법을 사용하여 부분적으로 적용할 수 있다.

  105년 = (+ 5) 5   106년 = (5 +) 5      5를 더하다 = (5 +)   107년 = 5를 더하다 5 

포괄 목록

Haskell 예제에 대한 자세한 내용은 목록 이해력#개요를 참조하십시오.

패턴 매칭

패턴 매칭은 대수 데이터 유형의 다른 생성자를 일치시키기 위해 사용된다. 다음은 아래 각 유형에서 패턴 일치를 사용하는 몇 가지 기능이다.

-- 이 타입 서명은 비어있는 타입이 모든 타입을 포함하는 리스트를 가지고 있고, Bool을 반환한다. 텅 빈 :: [a] ->  텅 빈 (x:xs) = 거짓의 텅 빈 [] = 진실의  -- 아무것도 없는 경우 기본값으로 지정된 Maybe a에서 값을 반환함 아마도 :: a -> 어쩌면 a -> a 아마도 x (그냥 y) = y 아마도 x 아무 것도 없어요.  = x  옳다 :: 어느 쪽이든 a b ->  옳다 (맞다 _) = 진실의 옳다 (왼쪽 _)  = 거짓의  getName :: 사람 ->  getName (사람 이름을 붙이다 _ _) = 이름을 붙이다  겟섹스 :: 사람 -> 섹스 겟섹스 (사람 _ 섹스를 _) = 섹스를  게티지 :: 사람 -> 인트 게티지 (사람 _ _ 나이를 먹다) = 나이를 먹다 

위의 함수와 함께 목록의 각 요소에 적용하여 결과를 볼 수 있다.

지도를 그리다 텅 빈 [[1,2,3],[],[2],[1..]] -- 반환 [거짓, 참, 거짓, 거짓]  지도를 그리다 (아마도 0) [그냥 2,아무 것도 없어요.,그냥 109238, 아무 것도 없어요.] -- 반환 [2,0,162238,0]  지도를 그리다 옳다 [왼쪽 "안녕", 맞다 6, 맞다 23, 왼쪽 "세계"] -- 반환 [거짓, 참, 참, 거짓]  지도를 그리다 getName [사람 "사라" 여성 20, 사람 "알렉스" 남성 20, 톰.] -- 위의 Tom에 대한 정의를 사용하여 ["Sarah", "Alex", "Tom"을 반환함 
  • 추상 유형
  • 목록

투플스

해스켈의 튜플은 일정한 수의 원소를 고정하는 데 사용될 수 있다. 이러한 데이터는 서로 다른 유형의 데이터를 그룹화하는 데 사용된다.

회계 :: (, 정수, 더블) -- 삼투플의 유형으로, 대표적이다.                                       - 이름, 잔액, 이자율 회계 = ("존 스미스",102894,5.25) 

튜플은 일반적으로 별도의 리스트에 인접한 요소들을 함께 배치하기 위해 zip* 함수에 사용된다(zip4에서 zip7까지 데이터에서 제공).목록 모듈:

-- zip 함수의 정의. 다른 zip* 함수도 유사하게 정의됨 지퍼를 채우다 :: [x] -> [y] -> [(x,y)] 지퍼를 채우다 (x:xs) (y:ys) = (x,y) : 지퍼를 채우다 xs ys 지퍼를 채우다 _      _      = []  지퍼를 채우다 [1..5] "안녕" - returns [(1,'h',(2,'e'),(3,'l'),(4,'l'),(5,'o')] - 그리고 유형 [(Integer, Char)]이 있음  지퍼3 [1..5] "안녕" [거짓의, 진실의, 거짓의, 거짓의, 진실의] - returns [(1,h,false), (2,'e',True), (3,'l',False), (4,'l',False), (5,'o',True)] - 그리고 유형 [(Integer, Char, Bool)]이 있음 

GHC 컴파일러에서 튜플은 2개 요소에서 최대 62개 요소까지의 크기로 정의된다.

네임스페이스

위의 #More_complex_explices 섹션에서, calc Haskell 유형 클래스 네임스페이스와 값을 위한 네임스페이스가 있음을 보여주는 두 가지 의미로 사용된다.

  1. 에 대한 하스켈식 수업. calc도메인범위는 Haskell 유형 클래스에서 명시적으로 나타낼 수 있다.
  2. 에 대한 하스켈 값, 공식 또는 표현식 calc.

유형 분류 및 다형성

대수 데이터 유형

대수 데이터 유형은 하스켈에서 광범위하게 사용된다. 이것들의 몇 가지 예는 빌트인 목록이다. Maybe 그리고 Either 유형:

-- a([a])의 목록은 a의 다른 목록에 동의된(:)이거나, 빈 목록([])이다. 자료 [a] = a : [a]   [] -- 어떤 종류의 것 a는 그냥 어떤 것일 수도 있고, 아무것도 아닐 수도 있다. 자료 어쩌면 a = 그냥 a   아무 것도 없어요. -- something something atype btype은 Left attype 또는 Right btype이다. 자료 어느 쪽이든 a b = 왼쪽 a   맞다 b 

언어 사용자들은 또한 그들 자신의 추상적인 데이터 유형을 정의할 수 있다. 사람의 이름, 성별, 나이를 나타내는 ADT의 예는 다음과 같이 보일 수 있다.

자료 섹스 = 남성   여성 자료 사람 = 사람  섹스 인트 -- Person은 생성자일 뿐 아니라 유형이라는 점에 주목하십시오.  -- Person 타입의 무언가를 만드는 예 톰. :: 사람 톰. = 사람 "톰" 남성 27 

유형 시스템

  • 유형 클래스
  • 기본 설정 입력
  • 과부하 리터럴
  • 고품격 다형성
  • 다중 매개변수 유형 클래스
  • 기능 종속성

모나드 및 입력/출력

ST 모나드

ST 모나드는 프로그래머가 돌연변이 변수(STREF)와 돌연변이 배열(STARrays and STUArrays)을 사용하여 하스켈에서 명령 알고리즘을 작성할 수 있도록 한다. ST모나드의 장점은 프로그래머가 변이 가능한 변수와 배열을 파괴적으로 업데이트하는 등 내부 부작용이 있는 코드를 작성할 수 있는 동시에 이러한 효과를 모나드 내부에 담을 수 있다는 점이다. 그 결과 ST monad를 사용하여 작성된 기능은 프로그램의 나머지 부분에는 완전히 순수하게 나타난다. 이를 통해 프로그래머는 기능 코드를 작성하는 것이 비실용적일 수 있는 필수 코드를 만들 수 있으며, 순수 코드가 제공하는 모든 안전성은 그대로 유지할 수 있다.

다음은 숫자 목록을 가져다가 변이 가능한 변수를 사용하여 요약하는 예제 프로그램(ST 모나드의 Haskell wiki 페이지에서 가져온)이다.

수입하다 통제하다.모나드.ST 수입하다 데이터.STREF 수입하다 통제하다.모나드  섬스트 :: 숫자 a => [a] -> a 섬스트 xs = 런스트 $ 하다            -- runST는 stateful ST code를 취하여 순수하게 만든다.     총계한 <- newSTRef 0         -- STRef(변수 변수) 만들기      forM_ xs $ \x -> 하다          -- 인수 목록의 각 요소에 대해 xs ..         수정STRef 총계한 (+x)  &shy; n에 있는 것에 그것을 더하기.      readSTRef 총계한             -- 위의 runST에 의해 반환될 n의 값을 읽으십시오. 

STM 모나드

STM 모나드는 Haskell에서 소프트웨어 트랜잭션 메모리를 구현한 것이다. GHC 컴파일러에서 구현되며, 트랜잭션에서 변이 가능한 변수를 수정할 수 있다.

화살표

  • 응용 펑커스
  • 화살표

하스켈은 순수한 기능 언어인 만큼 기능은 부작용이 있을 수 없다. 엄격하지 않다 보니 평가 순서도 제대로 정립되지 않았다. 이것은 실제 프로그램에 대한 도전이며, 무엇보다도 환경과 상호 작용해야 한다. Haskell은 명령형 구조의 적절한 순서를 보장하기 위해 형식 시스템을 이용하는 단색형으로 이것을 해결한다. 대표적인 예가 I/O이지만, 모노드는 돌연변이 상태, 동시성 및 트랜잭션 메모리, 예외 처리, 오류 전파 등 다른 많은 목적에 유용하다.

Haskell은 단음절 표현에 대한 특별한 구문을 제공하여 부작용 프로그램이 현재의 명령형 프로그래밍 언어와 유사한 스타일로 작성될 수 있도록 한다. 단음절 I/O 뒤에 있는 수학에 대한 지식은 필요하지 않다. 다음 프로그램은 명령줄에서 이름을 읽고 인사말을 출력한다.

본래의 = 하다 putStrLn "이름이 뭐야?"           이름을 붙이다 <- getLine           퍼트스트 ("안녕, " ++ 이름을 붙이다 ++ "!\n") 

그 공지는 모노드를 가지고 일하는 것을 용이하게 한다. 이러한 표현은 단색 연산자를 직접 사용하는 보다 쓰기 및 이해하기가 (논의할 수 없이) 쉽다.

본래의 = putStrLn "이름이 뭐야?" >> getLine >>= \ 이름을 붙이다 -> 퍼트스트 ("안녕, " ++ 이름을 붙이다 ++ "!\n") 
위키북을 참조하십시오.트랜스위키:헬로 월드 프로그램 목록#해스켈, 텍스트를 인쇄하는 또 다른 예.

동시성

Haskell 언어 정의 자체는 GHC가 둘 다 지원하지만 동시성이나 병렬성을 포함하지 않는다.

Concurrent Haskell은 스레드 및 동기화를 지원하는 Haskell에 대한 확장이다.[7] GHC의 Concurrent Haskell 구현은 경량 Haskell 스레드를 몇 개의 헤비급 OS 스레드에 멀티플렉싱하여 Concurrent Haskell 프로그램이 멀티프로세서에서 병렬로 실행되도록 하는 것에 기초한다.[8] 런타임은 수백만 개의 동시 스레드를 지원할 수 있다.[9]

GHC 구현은 OS 스레드의 동적 풀을 채택하여, Haskell 스레드가 실행 중인 다른 Haskell 스레드를 차단하지 않고 차단 시스템 호출을 할 수 있다.[10] 따라서 경량 Haskell 스레드는 헤비급 OS 스레드의 특성을 가지고 있으며, 프로그래머는 구현 세부사항을 알지 못한다.

최근 Concurrent Haskell은 공유 데이터에 대한 복합 연산이 원자로 수행되는 동시성 추상화인 STM(Software Transactional Memory)을 거래로 지원하면서 확장되고 있다.[when?][11] GHC의 STM 구현은 현재까지 거래 내에서 비거래 작업이 수행되는 것을 방지하는 정적 컴파일 시간 보증을 제공하는 유일한 STM 구현이다. 또한 Haskell STM 라이브러리는 다른 STM에서 찾을 수 없는 두 가지 작업을 제공한다. retry 그리고 orElse모듈형 복합형 방식으로 차단 작업을 정의할 수 있도록 한다.

참조

  1. ^ 하스켈위키: 서명을 올바른 스타일로 입력하십시오.
  2. ^ 하스켈위키: 포인트프리
  3. ^ "Prime numbers - HaskellWiki". www.haskell.org.
  4. ^ "Prime numbers - HaskellWiki". www.haskell.org.
  5. ^ 오닐, 멜리사 E, "에라토스테네스의 정품", 기능 프로그래밍 저널, 캠브리지 대학 출판부가 2008년 10월 9일 온라인 출판한 2008년 10월 10일 도이:10.1017/S0956796808004, 페이지 10, 11.
  6. ^ "Prime numbers - HaskellWiki". www.haskell.org.
  7. ^ 사이먼 페이튼 존스, 앤드류 고든, 그리고 시그존 피네. Concurrent Haskell. ACM SIGPlan-SIGACT 프로그래밍 언어 원리 심포지엄(PoPL) 1996. (현재 구현과 관련하여 일부 섹션은 구식이다.)
  8. ^ Multicore Haskell에 대한 런타임 지원 웨이백 머신(Simon Marlow, Simon Peyton Jones, Satnam Singh)에 보관된 2010-07-05: 2009년 8월, 에든버러, 에든버러, 기능 프로그래밍에 관한 제14차 ACM SIGLAN 국제회의 진행
  9. ^ "DEFUN 2009: Multicore Programming in Haskell Now!". 5 September 2009.
  10. ^ 웨이백 머신(Simon Marlow, Simon Peyton Jones, Wolfgang Thaller)에서 2010-07-03을 아카이브한 Haskell 대외 기능 인터페이스 확장 Haskell 57-68, Snowbird, Utah, Snowbird, 2004년 9월
  11. ^ Harris, Tim; Marlow, Simon; Peyton-Jones, Simon; Herlihy, Maurice (2005). "Composable memory transactions". Proceedings of the tenth ACM SIGPLAN symposium on Principles and practice of parallel programming. CiteSeerX 10.1.1.67.3686.