2010-02-08 4 views
32

하스켈에서 패턴 매칭이란 무엇이며 어떻게 보호 된 방정식과 관련이 있습니까?하스켈 패턴 매칭 - 뭔데?

간단한 설명을 찾아 보았습니다 만 찾지 못했습니다.

편집 : 누군가 숙제로 표시됩니다. 나는 더 이상 학교에 가지 않으며, 나는 하스켈을 배우는 중이고이 개념을 이해하려고 노력하고 있습니다. 순수한 관심.

+4

또한 F #의 패턴 일치 개념을 포함해야합니다. –

+1

언어 톤은 하스켈 및 F #뿐만 아니라 패턴 일치도 있습니다. – Joe

+1

순수 함수 및 제약 언어의 공통된 특징입니다. Prolog, Erlang 및 SML 등이 있습니다. – outis

답변

52

간단히 말해서 패턴은 수학에서 구분 기능을 정의하는 것과 같습니다. 패턴을 사용하여 다른 인수에 대해 다른 함수 본문을 지정할 수 있습니다. 함수를 호출하면 실제 인수를 다양한 인수 패턴과 비교하여 적절한 본문을 선택합니다. 자세한 내용은 A Gentle Introduction to Haskell을 참조하십시오.

비교 :

Fibonacci sequence

등가 하스켈으로 :

fib 0 = 1 
fib 1 = 1 
fib n | n >= 2 
     = fib (n-1) + fib (n-2) 

참고 "N ≥ 2의"불연속 함수 하스켈 버전 가드 지지만,이 다른 두 조건은 단순한 패턴입니다. 패턴은 x:xs, (x, y, z) 또는 Just x과 같이 값과 구조를 테스트하는 조건입니다. 조각 별 정의에서는 = 또는 관계를 기반으로하는 조건 (기본적으로 어떤 것이 "뭔가"라고 말하는 조건)이 패턴이됩니다. 경비원은보다 일반적인 조건을 허용합니다. 우리는 fib는 가드를 사용하여 다시 작성할 수 :

fib n | n == 0 = 1 
     | n == 1 = 1 
     | n >= 2 = fib (n-1) + fib (n-2) 
+0

결코 이것에 대한 더 나은 설명을 보지 못했습니다! +1. [이 F # doc] (http://msdn.microsoft.com/en-us/library/dd547125.aspx)도 멋지다. – nawfal

3

을 기능적인 언어로, 패턴 매칭은 다른 형태에 대한 인수를 확인하는 것을 포함한다. 간단한 예제는 목록에 대한 재귀 적으로 정의 된 작업을 포함합니다. OCaml을 사용하여 필자가 선택한 함수 언어이므로 패턴 일치를 설명 할 것이지만 개념은 F #과 Haskell, AFAIK에서 동일합니다.

다음은 목록의 길이를 계산하는 함수의 정의입니다. lst. OCaml에서,리스트는 요소와리스트로부터 새로운리스트를 생성하는 cons 연산자입니다.

그래서 함수는 다음과 같습니다

let rec len lst = 
    match lst with 
    [] -> 0 
    | h :: t -> 1 + len t 

rec는 함수가 자신을 재귀 적으로 호출하는 것이 OCaml의를 알려주는 수정입니다. 그 부분에 대해 걱정하지 마십시오. match 성명서는 우리가 중점적으로 다루는 내용입니다. OCaml은 lst을 빈리스트 또는 h :: t과 같은 두 패턴과 대조하여 그 값에 따라 다른 값을 반환합니다. 모든 목록이 이러한 패턴 중 하나와 일치한다는 것을 알고 있기 때문에 함수가 안전하게 반환된다는 것을 확신 할 수 있습니다.

이 두 패턴이 모든 목록을 처리하지만 사용자가이 목록에 제한되지는 않습니다. h1 :: h2 :: t (길이가 2 이상인 모든 목록과 일치)과 같은 패턴도 유효합니다.

물론 패턴의 사용은 재귀 적으로 정의 된 데이터 구조 나 재귀 함수에만 국한되지 않습니다.여기에 숫자가 1 또는 2 여부를 알려주는 (인위적인) 함수 :이 경우

let is_one_or_two num = 
    match num with 
    1 -> true 
    | 2 -> true 
    | _ -> false 

는, 우리의 패턴의 형태는 숫자 그 자체입니다. _은 위의 패턴 중 어느 것도 일치하지 않는 경우를 대비하여 기본 사례로 사용되는 특수한 catch-all입니다.

12

패턴 매칭 하스켈 적어도 깊이 algebraic data types의 개념에 묶여있다. 이 같은 데이터 유형 선언 할 때 :

data SomeData = Foo Int Int 
       | Bar String 
       | Baz 

를 ... 그것은 FooBar을 정의하고, Baz등의 생성자 알리바이는 OOP에서 "생성자"와 혼동 - 그는 SomeData 값을 작성 다른 값들 중에서.

패턴 매칭은 사실, 난 그 패턴 매칭은 값을 추출하는 유일한 방법입니다 믿고 (그 구성 조각으로 SomeData 값을 "해체 것"이라고 반대 --a 패턴이하는 것보다 아무것도 더 하스켈).

유형에 대해 여러 생성자가있는 경우 각 패턴에 대해 여러 버전의 함수를 작성하고 올바른 생성자는 사용 된 생성자에 따라 선택됩니다 (모든 가능한 구성에 일치하는 패턴을 작성했다고 가정 할 때 - 그것은 일반적으로 좋은 연습입니다).

+1

"함수의 여러 버전"은 case 문에 대한 구문 설탕입니다. http://learnhaskell.blogspot.com/2007/09/lesson-3-case-3.html –

1

패턴 매칭은 절차 적 프로그래밍 배경에서 오는 경우 주변 사람의 머리를 얻기 어려운 그 고통스러운 작업 중 하나입니다. 데이터 구조를 만드는 데 사용 된 구문과 동일한 구문을 사용하여 일치시키기가 어려워졌습니다.

F 번호에서 당신과 같이 목록의 시작 부분에 요소를 추가 할 단점 연산자 ::를 사용할 수 있습니다

let a = 1 :: [2;3] 
//val a : int list = [1; 2; 3] 

는 마찬가지로 당신과 같이 목록을 분할하기 위해 같은 연산자를 사용할 수 있습니다

let a = [1;2;3];; 
match a with 
    | [a;b] -> printfn "List contains 2 elements" //will match a list with 2 elements 
    | a::tail -> printfn "Head is %d" a //will match a list with 2 or more elements 
    | [] -> printfn "List is empty" //will match an empty list 
+1

"... 같은 구문 데이터 구조를 만드는 데 사용되어 일치하는 데 사용될 수 있습니다. "- 거의 요점입니다. 패턴 매칭을 사용하여 값을 만드는 데 사용 된 생성자를 찾습니다. Norman Ramsey 또는 camccann의 답변을 참조하십시오. 또한 cons가 단순히 길이 (length) 나 연결 (concatenate)와 같은 목록에 작용하는 함수가 아니라리스트 생성자라는 사실을 깨닫는 데 도움이됩니다. 물론 피보나치 예제에서 볼 수 있듯이, 0 또는 1과 같은 특정 값과 cons 나 Just와 같은 생성자 (Haskell의 일반적인 값)에 패턴 매치를 적용 할 수 있습니다. – Nefrubyr

23

는 다른 좋은 답이있다, 그래서 나는 당신에게 매우 기술적 인 대답을거야.

  • "제거는 구성이"의 "소비하거나 값 사용」외에

  • "대수 데이터 유형 "을 의미 패턴 매칭은 제거가 대수 데이터 유형위한를 구성이며 일류 기능, 청소, F 번호, 하스켈, 또는 ML

같은 정적으로 입력 된 함수형 언어의 큰 아이디어는 대수 데이터 유형의 아이디어입니다 당신은 일종의 일을 정의하고, 당신은 그 일을 할 수있는 모든 방법을 말합니다. 예를 들어, 현실을 만드는 세 가지 방법으로, 대수 데이터 형식으로 "문자열의 순서를"정의 할 수 있습니다 :이 정의 문제, 모든 일이있다, 지금

data StringSeq = Empty     -- the empty sequence 
       | Cat StringSeq StringSeq -- two sequences in succession 
       | Single String   -- a sequence holding a single element 

하지만, 예로서 흥미 롭군요 이는 임의의 길이의 시퀀스를 일정 시간에 연결하기 때문입니다. (이를 달성하는 다른 방법이 있습니다.) 선언은 Empty, CatSingle을 소개하며 모든 방법은 시퀀스를 만듭니다.. (즉, 각 하나는 도입이 일을 할 수있는 방법을 — 구성 수 있습니다.)

  • 당신은 어떤 다른 값없이 빈 시퀀스를 만들 수 있습니다.
  • Cat으로 시퀀스를 만들려면 두 개의 다른 시퀀스가 ​​필요합니다. , 제거 구조, 패턴 매칭 당신에게 순서를 자세히 조사하고 질문 할 수있는 방법을 제공합니다 :
  • 여기

펀치 라인을 제공합니다 (이 경우 문자열) 요소가 필요 Single와 시퀀스를 만들려면 그 질문은 당신은 어떤 생성자로 만들었습니까?. 어떤 대답을 대비해야하기 때문에 각 생성자에 대해 적어도 하나의 대안을 제공해야합니다. 여기에 길이 함수의 :

slen :: StringSeq -> Int 
slen s = case s of Empty -> 0 
        Cat s s' -> slen s + slen s' 
        Single _ -> 1 

언어의 핵심은, 모든 패턴 매칭이 case 구조에 내장되어 있습니다. 대수 데이터 유형 및 패턴 매칭 언어의 숙어에 매우 중요하기 때문에, 함수 정의의 선언 형태로 패턴 매칭을 수행하기위한 특별한 "문법 설탕"거기에이 문법적으로

slen Empty = 0 
slen (Cat s s') = slen s + slen s' 
slen (Single _) = 1 

는, 패턴 매칭에 의한 계산은 방정식에 의한 정의와 비슷합니다. (하스켈위원회는 이것을 목적으로했다.) 그리고 다른 답에서 알 수 있듯이, case 표현식에서 방정식이나 대안을 전문화 할 수있다. 시퀀스 예제에서 그럴듯한 가드를 생각할 수 없으며 다른 답변에는 많은 예제가 있으므로 여기에 남겨 두겠습니다.