7

나는 사람들이 에 대해 이야기하는 것을 보았습니다. 귀하의 상반기를 스크랩일반 프로그래밍 하스켈에서. 이 용어들은 무엇을 의미합니까? Your Boiler Plate를 언제 사용하고 싶고, 어떻게 사용합니까?"귀하의 상용구를 스크랩 (Scrap Your Boilerplate)"이란 무엇입니까?

+1

구글은 이것에 관한 많은 문서를 가지고있다 .... –

+3

@JustinPihony Stack Overflow의 목표 중 하나는 모든 프로그래밍 관련 질문에 대한 답을 얻는 것이기 때문에 질문을했다. (http://meta.stackexchange.com/questions/5280/embrace-the-non-googlers). 이 질문은 제가 볼 수있는 한 지금까지 한번도 묻지 않았습니다. 그리고 저는 그것이 고품질의 답변을 얻을 것이라고 믿습니다. –

+0

논문의 섹션 2 [일반 프로그래밍을위한 실용적인 디자인 패턴] (http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=0088DE3D75D657BE9F2B9E5D705232B3?doi=10.1.1.1.3176&rep=rep1&type= pdf)에는 좋은 동기 부여 예제가 들어 있습니다. – ErikR

답변

7

종종 복잡한 데이터 유형에 대한 변환을 수행 할 때 구조의 작은 부분에만 영향을 주어야합니다. 즉, 특정 축소 가능 표현식, redexes만을 대상으로합니다.

고전적인 예는 정수 표현의 유형을 통해 이중 부정 제거입니다 :

data Exp = Plus Exp Exp | Mult Exp Exp | Negate Exp | Pure Int 

doubleNegSimpl :: Exp -> Exp 
doubleNegSimpl (Negate (Negate e)) = e 
... 

에도이 예제를 설명하기에, 나는 ... 부분의 전체를 작성하지 않으려는 것입니다. 이것은 완전히 기계적입니다. Exp 전체를 통해 재귀를 계속하기위한 엔진 이상의 것은 아닙니다.

"엔진"은 스크랩하려는 상용구입니다.


이 목표를 달성하기 위해 스크랩 Your Boilerplate는 데이터 유형에 대해 "일반 트래버스"를 구성 할 수있는 메커니즘을 제안합니다. 이 트래버스는 문제의 특정 데이터 유형에 대해 전혀 모른 채 정확하게 작동합니다. 이렇게하기 위해서는 매우 대략적으로 우리는 일반적인 주석이 달린 나무의 개념을 가지고 있습니다.

section :: Generic a => a -> AnnotatedTree 

하고 "유효"주석 나무

retract :: Generic a => AnnotatedTree -> Maybe a 
ADT

일부 브랜드로 다시 투사 할 수 있습니다 :이 모든 ADT를이 주석이 달린 나무의 종류에 투사 할 수있는 방식으로 ADT를보다 큰

특히, sectionretract이 정의 된 유형을 나타 내기 위해 Generic typeclass를 도입하려고합니다.

모든 데이터 유형의 주석 된 트리 표현을 사용하여 한 번만 트래 버셜을 정의 할 수 있습니다. 특히 최종 사용자가 AnnotatedTree 유형에 노출되지 않도록 (sectionretract 전략적으로) 인터페이스를 제공합니다. 최종 초기 sectionretract들과 함께 우리의 주석이 나무는 항상 "유효"이라는 불변

everywhere' :: Generic a => (a -> a) -> (AnnotatedTree -> AnnotatedTree) 

같은 것을, 우리가

everywhere :: Generic a => (a -> a) -> (a -> a) 
everywhere f a0 = fromJust . retract . everywhere' f . section 

이 : 대신, 비트처럼 보인다

everywhere f a의 기능은 무엇입니까? ADT a에 "everywhere"함수 f을 적용하려고 시도합니다. 즉

doubleNegSimpl :: Exp -> Exp 
doubleNegSimpl (Negate (Negate e)) = e 
doubleNegSimpl e     = e 

을 다음과 같이 즉, 우리는 지금, 우리의 이중 부정 단순화 쓰기 REDEX (Negate (Negate _))이 일치하도록 실패 할 때마다 그것은 id 역할을합니다. 우리는이

simplify :: Exp -> Exp 
simplify = everywhere doubleNegSimpl 

두 번 부정에 everywhere를 적용하면 일반적인 탐색을 통해 "어디서나"제거 될 것입니다.... 상용구가 사라졌습니다.

+0

패턴이 성공적으로 일치하는지 여부를 'everywhere'가 어떻게 알 수 있습니까? 대개 비 - 철저한 패턴은 예외를 던져서'IO'에서 잡아야 만한다. –

+0

그렇지 않습니다. 'doubleNegSimpl'은 redex가 일치하지 않을 때 identity입니다. 그래서'everywhere'는 사실상 모든 곳에서 적용됩니다 * 그리고 대부분의 장소에서 단순히 no-op입니다. 물론, '어디에서나'효율적으로 이것을 수행하는 데주의해야합니다. –

+0

아 물론. 나는 분명히 신중하게 읽지 않았다;) –

관련 문제