2009-10-20 4 views
4

매우 제한된 하스켈 -fu에 실례합니다.Haskell에서 구조적으로 비슷한 유형의 값으로 조작하십시오.

-- in module Foo 
data Foo = Foo [Param] 

-- in module Bar 
data Bar = Bar [Param] 

-- * many more elsewhere 

내가 PARAMS 목록 예에서 작동 함수의 집합을 가지고 싶습니다

나는 같은 방식으로 구성되어 다른 모듈에 정의 된 data 종류의 시리즈를 가지고 목록에서 요소를 추가 및 제거합니다 (적절한 경우 새 Foo 또는 Bar을 다른 매개 변수 목록으로 반환).

는 지금까지 내가 말할 수있는, 내가 typeclass를 작성하고 각 유형의 인스턴스를 생성 할 경우에도, 나는 이러한 기능마다 모두를 정의 할 필요가 거라고 예 :

-- in some imported module 

class Parameterized a where 
    addParam :: a -> Param -> a 
    -- ... other functions 

-- in module Foo 

instance Parameterization Foo where 
    addParam (Foo params) param = Foo (param:params) 
    -- ... other functions 

-- in module Bar 

instance Parameterization Bar where 
    -- this looks familiar... 
    addParam (Bar params) param = Bar (param:params) 
    -- ... other functions 

이 지루한 느낌 - - 내가 뭔가 잘못하고 있다고 생각하기 시작한 정도를 훨씬 넘어서. 값을 추출하기 위해 생성자 (?)에 관계없이 패턴 일치를 수행 할 수 없다면 어떻게 이와 같은 상용구를 줄일 수 있습니까?

가능한 인수 행을 반박하려면 : 예, 함수 (addParam 등)를 하나만 가지고 있으면 각 생성자와 패턴 일치를 명시 적으로 나열 할 수 있음을 알 수 있습니다. 그러나 필자가 작성하고 있습니다. 이 상당히 모듈화 (FooBar 모듈은 꽤 독립적입니다.) 그리고 이러한 유형이 수십 가지가 될 시스템을 프로토 타이핑하고 있습니다. 형식 생성자의 자세한 중앙 집중식 목록이 잘못된 것처럼 보입니다.

필자의 접근 방식에 결함이 있다는 것과 어쨌든 형식 계층을 구조화하는 데 올바른 방법이 어디에도 없다는 것을 알 수 있습니다. 그러나 data 형식을 어딘가에 추가 할 수는 없으므로 이러한 각 모듈의 유형에 대한 새로운 생성자 (?) 나는 간단한 유틸리티 함수를 매번 다시 정의 할 필요없이 멋진 "플러그인"느낌을 얻는 방법에 난처한 입장입니다. 모든 종류의 제안이 기꺼이 받아 들여졌습니다.

+0

왜 Foo Bar 유형을 사용하고 목록을 사용하지 않는가? – yairchu

답변

4

typeclass에 함수의 기본 구현을 포함 할 수 있습니다 (예 :

class Parameterized a where 
    params :: a -> [Param] 
    fromParams :: [Param] -> a 
    addParam :: a -> Param -> a 
    addParam x par = fromParams $ par : params x 
    -- ... other functions 

instance Parameterized Foo where 
    params (Foo pars) = pars 
    fromParams = Foo 

그러나 디자인이 의심스러워 보입니다.

2

올바른 예가 무엇인지 예를 들어 설명하기가 어렵습니다.

구조적으로 유사한 경우 왜 FooBar이 모두 필요합니까? Foo으로 갈 수 없습니까?

어떤 이유인지 모르겠지만 FooBar이 모두 필요하다면 유형 클래스를 사용해야하지만 템플릿 하스켈을 사용하여 코드를 정리할 수 있습니다.

뭔가

처럼
$(superDuper "Foo") 

코드

data Foo = Foo [Param] 

instance Parameterization Foo where 
    addParam (Foo params) param = Foo (param:params) 

을 생성 할 수있는 곳 이상의 보일러 플레이트 코드를 제거 할

superDuper :: String -> Q [Dec] 
superDuper n = 
    let name = mkName n 
     dataD = DataD [] name [] [NormalC name [] ] -- correct constructor here 
     instD = InstanceD [] ... -- add code here 
    return [dataD, instD] 

.

+0

잠시 동안 템플릿 하스켈을 확인하고 싶습니다. 이 예제에 감사드립니다. –

3

Foo 및 Bar에 newtype을 사용하고 기본 구조 (이 경우 목록)를 기반으로 구현을 -XGenerializedNewtypeDeriving으로 자동 파생시킬 수 있습니다.

실제로 구조적으로 유사하지만 코드를 공유 할 수 없도록 코딩 한 경우 의심스러운 패턴입니다.

관련 문제