수색…


강타 패턴

강타 ( ! )로 주석이 달린 패턴은 느리게 대신 엄격하게 평가됩니다.

foo (!x, y) !z = [x, y, z] 

이 예제에서 xz 는 모두 목록을 반환하기 전에 weak head normal form으로 평가됩니다. 그것은 다음과 같습니다 :

foo (x, y) z = x `seq` z `seq` [x, y, z]

Bang 패턴은 Haskell 2010 BangPatterns 언어 확장을 사용하여 활성화됩니다.

일반 양식

이 예제는 간단한 개요를 제공합니다. 일반적인 양식 과 예제에 대한 자세한 설명은 이 질문을 참조하십시오.

감소 된 정상형

표현식의 감소 된 정상형 (또는 정상적인 형태, 문맥이 명확 할 때)은 주어진 표현식에서 모든 축소 가능한 부분 표현식을 평가 한 결과입니다. 하스켈의 비 엄격한 의미론 (일반적으로 게으름 이라고 함)으로 인해 바인더 아래에있는 경우 하위 표현식을 줄일 수 없습니다 (예 : 람다 추상화 - \x -> .. ). 표현식의 정규형은 존재하는 경우 고유 한 특성을 갖습니다.

즉, 하위 표현식을 줄이는 순서 (의미 적 의미론의 측면에서)는 중요하지 않습니다. 그러나 퍼포먼스 하스켈 프로그램을 작성하는 열쇠는 올바른 표현이 적시에 평가되는 것을 보장하는 것, 즉 운영 의미론을 이해하는 것입니다.

그 정규형 식은 자체는 정상 형태로 알려져있다.

일부 표현식 (예 : let x = 1:x in x )은 정규 양식이 없지만 여전히 생산적입니다. 무제한 값을 허용하는 경우 예제 식은 여전히 값을 가지며 여기에는 [1,1, ...] 목록이 있습니다. let y = 1+y in y 와 같은 다른 표현식에는 값이 없거나 그 값은 undefined .

약한 머리 정상형

RNF는 표현식을 완전히 평가하는 것과 같습니다. 마찬가지로 약한 머리 정규형 (WHNF)은 표현의 머리 를 평가하는 것과 같습니다. 표현식 e 의 머리 부분은 e 가 응용 프로그램 일 경우 완전히 평가됩니다 Con e1 e2 .. enCon 은 생성자입니다. 또는 추상화 \x -> e1 ; 또는 부분적인 어플리케이션 f e1 e2 .. en , 부분적인 어플리케이션 fn 개 이상의 인수를 취하는 것을 의미합니다 (또는 등가 적으로, e 의 타입은 함수 타입입니다). 어쨌든, 부분 식 e1..ene1..en 에있는 식에 대해 평가되거나 평가되지 않을 수 있습니다. 심지어 undefined 않을 수도 있습니다.

Haskell의 평가 의미는 WHNF로 표현 될 수있다. - 표현식 e 를 평가하고, 먼저 WHNF로 평가 한 다음, 모든 하위 표현식을 왼쪽에서 오른쪽으로 재귀 적으로 평가한다.

원시 seq 함수는 표현식을 WHNF로 평가하는 데 사용됩니다. seq xy 는 표기법 상 y 같습니다 ( seq xy 의 값은 정확하게 y ). 또한 y 가 WHNF로 평가 될 때 x 는 WHNF로 평가됩니다. 식은 다음과 같이 구문이있는 -XBangPatterns 확장명으로 활성화 된 bang 패턴을 사용하여 WHNF로 평가할 수도 있습니다.

f !x y = ... 

여기서 f 는 평가 될 때 x 가 WHNF로 평가되고 y 는 (필연적으로) 평가되지 않습니다. 강타 패턴은 생성자에 나타날 수도 있습니다.

data X = Con A !B C .. N

이 경우 생성자 ConB 필드에서 엄격한 것으로, 이는 생성자가 충분한 (여기, 2 개의) 인수에 적용될 때 B 필드가 WHNF로 평가된다는 것을 의미합니다.

게으른 패턴

게으른 또는 반박 할 수없는 패턴 ( ~pat 구문으로 표시)은 일치하는 값을 보지 않고도 항상 일치하는 패턴입니다. 즉, 게으른 패턴은 하단 값과 일치합니다. 그러나 반박 불가능한 패턴의 하위 패턴에 바인드 된 변수를 계속 사용하면 일치가 발생하지 않는 한 아래쪽으로 평가되는 패턴 일치가 강제 실행됩니다.

다음 함수는 인수에서 느슨합니다.

f1 :: Either e Int -> Int
f1 ~(Right 1) = 42

그래서 우리는

λ» f1 (Right 1)
42
λ» f1 (Right 2)
42
λ» f1 (Left "foo")
42
λ» f1 (error "oops!")
42
λ» f1 "oops!"
*** type mismatch ***

다음 함수는 게으른 패턴으로 작성되었지만 실제로 일치를 강제하는 패턴의 변수를 사용하기 때문에 Left 인수에서 실패합니다.

f2 :: Either e Int -> Int
f2 ~(Right x) = x + 1

λ» f2 (Right 1)
2
λ» f2 (Right 2)
3
λ» f2 (Right (error "oops!"))
*** Exception: oops!
λ» f2 (Left "foo")
*** Exception: lazypat.hs:5:1-21: Irrefutable pattern failed for pattern (Right x)
λ» f2 (error "oops!")
*** Exception: oops! 

let 바인딩, 같은 반박 할 수없는 패턴을 게으른 행동하고 있습니다 :

act1 :: IO ()
act1 = do
    ss <- readLn
    let [s1, s2] = ss :: [String]
    putStrLn "Done"

act2 :: IO ()
act2 = do
    ss <- readLn
    let [s1, s2] = ss
    putStrLn s1

여기서 act1 은 모든 문자열 목록을 구문 분석하는 입력에 대해 작동하지만, act2 에서는 putStrLn s1[s1, s2] 대해 패턴 일치를 강제하는 s1 값을 필요로하기 때문에 정확히 두 문자열 목록에서만 작동합니다.

λ» act1
> ["foo"]
Done
λ» act2
> ["foo"]
*** readIO: no parse ***

엄격한 필드

data 선언에서 유형 앞에 접두사 ( ! )를 붙이면 필드가 엄격한 필드가 됩니다. 데이터 생성자가 적용되면 해당 필드는 약한 머리 일반 양식으로 평가되므로 필드의 데이터는 항상 약한 머리 일반 양식으로 보장됩니다.

엄격한 필드는 레코드 및 비 레코드 유형 모두에서 사용할 수 있습니다.

data User = User
    { identifier :: !Int
    , firstName :: !Text
    , lastName :: !Text
    }

data T = MkT !Int !Int


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow