2008-12-18 8 views
8

C++에서 나오기 때문에 제네릭 프로그래밍이 반드시 필요합니다. 사람들이 하스켈에서 어떻게 접근하는지 궁금하네요?하스켈에서 어떻게 일반 프로그래밍을합니까?

어떻게 하스켈에서 일반적인 스왑 기능을 작성합니까?

하스켈에는 부분 전문화와 동일한 개념이 있습니까?

C++에서는 O (1) 컨테이너 스왑을위한 특별한 스왑 메서드가있는 일반 맵/hash_map 컨테이너에 대해 특수 스왑 함수를 부분적으로 지정할 수 있습니다. 하스켈에서 이것을 어떻게합니까? 아니면 하스켈에서 일반적인 프로그래밍의 표준적인 예가 무엇입니까?

+31

이것은 농담입니다, 맞습니까? 이것은 어셈블리의 모든 것을 정확히 제어 할 수있는 방법을 묻는 것과 같습니다 : P – ShreevatsaR

+0

어셈블리와 관련된 작업은 없습니다. 알고리즘 패밀리와 동일한 인터페이스를 유지하면됩니다. – obecalp

+3

generic programming과 partial specialization (currying look up)에 관한 이상한 질문 외에도, "swapping variables"에 관한 질문은 이상합니다 : Haskell의 "두 상자의 내용 교환하기"와 같은 것이 없습니다. Haskell의 변수 데이터가있는 상자가 아닙니다. – ShreevatsaR

답변

27

이것은 Haskell 및 quicksort에 관한 다른 질문과 밀접하게 관련되어 있습니다. 적어도 하스켈에 관한 책 소개을 읽을 필요가 있다고 생각합니다. 기존 변수의 값을 수정하지 못하도록하는 요점을 아직 파악하지 못한 것 같습니다.

스왑 (C++에서 이해하고 사용함)은 본질적으로 기존 값을 수정하는 것과 관련되어 있습니다. 이름을 사용하여 컨테이너를 참조하고 완전히 다른 내용으로 해당 컨테이너를 바꾸고 특정 컨테이너에 대해 신속하고 예외적이지 않도록 해당 작업을 전문화하여 수정 및 게시 방법을 구현할 수 있습니다 (예외 안전 코드 작성 또는 잠금 해제 코드 작성에 중요).

하스켈에서 일반적인 스왑을 작성할 수는 있지만 한 쌍의 값을 가져 와서 같은 값을 포함하는 새 쌍을 반대로 또는 그와 비슷한 값으로 반환합니다. 실제로는 똑같은 것이 아니며 동일한 용도로 사용되지 않습니다. 하스켈에서 그런 일을 할 수 없기 때문에 맵 내부를 파고 개별 구성원 변수를 바꿔 맵에 특화 시키려고 시도하는 것은 이치에 맞지 않을 것입니다 (당신은 전문화를 할 수는 있지만 할 수는 없습니다. 변수 수정).

우리가 "측정"하스켈 목록에 원 가정 :

유형 선언의
measure :: [a] -> Integer 

. 즉, measure 함수는 아무 것도 나열하지 않고 (a은 소문자로 시작하므로 generic 형식 매개 변수 임) Integer를 반환합니다. 그래서 이것은 어떤 엘레멘트 타입의리스트에 대해 작동합니다 - C++에서 함수 템플릿이라고 부르는 것이거나 하스켈에서 다형 함수로 불리는 것입니다 (C++의 다형성 클래스와 같지 않음).

우리는 지금 각 흥미있는 경우에 전문을 제공함으로써 그것을 정의 할 수 있습니다

measure [] = 0 

즉 빈 목록을 측정하고 당신은 제로를 얻을.

measure (h:r) = 1 + measure r 

좌변에 괄호 안의 비트 패턴입니다 :

여기에 다른 모든 경우를 커버하는 아주 일반적인 정의입니다. 즉, 목록을 작성하고 머리를 잘라 h라고 부르며 나머지 부분 r을 호출합니다. 그런 이름은 우리가 사용할 수있는 매개 변수입니다. 이것은 적어도 하나의 항목이있는 목록과 일치합니다.

C++에서 템플릿 메타 프로그래밍을 시도했다면 이것은 완전히 동일한 스타일을 포함하기 때문에 오래된 것입니다. 즉, 반복을 수행하는 재귀, 재귀를 종료하는 전문화가 포함됩니다. Haskell을 제외하고는 런타임에 작동합니다 (특정 값 또는 값 패턴에 대한 함수의 특수화).

+0

스왑은 표준 C++ gp 예제입니다. Haskell 표준 예제를 사용하여 동일한 개념을 설명 할 수 있습니다. 나는 그것을 반영하기 위해 질문을 수정했다. – obecalp

9

Earwicker sais와 마찬가지로이 예제는 Haskell에서 그다지 의미가 없습니다. 당신이 절대적으로 어쨌든 그것을 가지고 싶다면, 여기에 대화 형 세션에서 & P C 비슷한 (한 쌍의 두 부분으로 교환)입니다 : 하스켈 책에서 충분히 읽은 후

GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help 
Loading package base ... linking ... done. 
Prelude> let swap (a,b) = (b,a) 
Prelude> swap("hello", "world") 
("world","hello") 
Prelude> swap(1,2) 
(2,1) 
Prelude> swap("hello",2) 
(2,"hello") 
+4

실제로이 값을 바꾸지는 않지만 원래 쌍이 변경 불가능하기 때문에 새 쌍을 반환한다는 점에 유의하십시오. – TheMarko

+0

ocaml과 매우 비슷합니다. 두 개의 해시 테이블이나 맵을 바꾸려면 값을 복사하지 않으려면 어떻게해야합니까? – obecalp

+0

큰 상태 테이블에서 작업하고 싶다면 처음에는 함수형 프로그래밍을 사용하고 싶지 않을 것입니다. 절대적으로 필요하다면 IORef와 상태를 유지하는 계산을 수행하는 상태 모나드가 있습니다. – TheMarko

2

을에 정말 Earwicker의 답변을 이해 나는 타입 클래스에 대해서도 읽어 보라고 권하고 싶다. 나는 "부분 전문화"가 무엇을 의미하는지 모르지만, 그들이 가까이 올 수있는 것처럼 들린다.

6

하스켈에서 함수는 가능한 한 일반적인 (다형성) - 컴파일러는 "가장 일반적인 형식"을 추론합니다. 예를 들어, TheMarko의 예를 스왑는 유형 서명이없는 경우 기본적으로 다형성 :

*>하자 홈페이지 스왑 (A, B) = (B, A)
* 홈페이지> : t 스왑
스왑 : - :
또한 file:///C:/ghc/ghc-6.10.1/doc/users_guide/pragmas.html#specialize-pragma

용어의 불일치가 있음에 유의 (t, T1)> (T1, t) 부분 특수화로서는

는 GHC 비 98 확장명을 갖는다. C++, Java 및 C#에서 generic이라고하는 것을 Haskell에서 다형성이라고합니다. 하스켈의 "Generic"은 일반적으로 폴리 타입을 의미합니다. http://haskell.readscheme.org/generic.html
그러나 aboe는 generic이라는 C++ 의미를 사용합니다.

+1

귀하의 링크가 죽었습니다 – Kos

+0

고마워, 둘 다 죽었어. 첫 번째 것도 링크가 아니야. 첫 번째 파일은 [link] http://lambda.haskell.org/platform/doc/current/ghc-doc/users_guide/pragmas.html#specialize-pragma이어야하며 두 번째 파일은 archive.org에서 찾을 수 있습니다. [link] http://web.archive.org/web/20080511185727/http://haskell.readscheme.org/generic.html –

5

하스켈에서는 유형 클래스를 생성합니다. 타입 클래스는 OO 언어의 클래스와 같지 않습니다. 숫자 형 클래스 가져 오기 클래스의 인스턴스 인 모든 것이 특정 작업 (+ - * /)을 수행 할 수 있으므로 Integer는 Numeric의 멤버이며 Numeric으로 간주되는 데 필요한 함수의 구현을 제공하며 어디에서나 사용할 수 있습니다. 숫자가 예상됩니다.

당신이 Ints and Strings를 foo 할 수 있기를 원한다고 가정 해 봅시다. 그런 다음 Int 및 String을 유형 Foo 클래스의 인스턴스로 선언합니다. 이제 어디에서나 유형 (Foo a)을 볼 수 있습니다. 이제 Int 또는 String을 사용할 수 있습니다.

정수 및 부동 소수점을 직접 추가 할 수없는 이유는 add가 (a 숫자) a -> a -> aa 유형 변수이기 때문에 일반 변수와 마찬가지로 한 번만 바인딩 될 수 있기 때문입니다. 곧 Int에 바인딩하면 목록의 모든 항목이 Int 여야합니다.

관련 문제