2016-09-01 6 views
2

이것은 내 문제의 단순화 된 버전입니다.하스켈의 팬텀 유형

필자는 재귀 적 데이터 구조 (Stream1)를 가지고 있습니다. 팬텀 유형 (스트림 a)을 도입하면 재귀 설명 (즉, t1)이 더 이상 작동하지 않습니다. 반면에 t2는 Stream1을 직접 사용하므로 무한한 구조를 생성하여 잘 작동합니다. t1에서와 같이 생성자 preI를 사용해야합니다. 내가 뭘 놓치고 있니? t1이 t2처럼 동작해야합니다. 즉, 무한 스트림을 반환합니다.

data Stream a = Stream Stream1 
    deriving (Eq, Show) 

data Stream1 = PreI Integer Stream1 
    deriving (Eq, Show) 

preI :: Integer -> Stream Int -> Stream Int 
preI n (Stream s) = Stream (PreI n s) 

t1 :: Stream Int 
t1 = let x = preI 0 x 
    in x 

t2 :: Stream Int 
t2 = let x = PreI 0 x 
    in Stream x 
+0

문제는 무엇인지 말하지 않았지만'Stream'을'newtype' ('data' 대신)으로 변경해보십시오. – melpomene

+0

(문제의 설명을 업데이트했습니다.) 예, 문제가 해결 된 것으로 보입니다. 많은 감사합니다! – ami

답변

6
preI :: Integer -> Stream Int -> Stream Int 
preI n (Stream s) = ... 
    -- ^^^^^^^^^^ 

이 패턴 매칭은 모든 출력이 생성되기 전에 인수 강제. 스트림의 경우 무한 스트림이 아닌 하단 (비 종단)에 최소 고정 소수점을 유지하므로이 방법이 좋지 않습니다.

대신 매칭 지연/반박 패턴을 시도 할 수

preI :: Integer -> Stream Int -> Stream Int 
preI n ~(Stream s) = Stream (PreI n s) 
    --^

을 이것은 본질적 의미 : 첫번째 입력을 풀기 시작에만 나중에 출력에 Stream, PreI를 생성하고

preI :: Integer -> Stream Int -> Stream Int 
preI n z = Stream (PreI n s) 
    where s = case z of Stream x -> x 

을 (s 사용시 발생).

Streamdata에서 newtype으로 변경됩니다. 이렇게하면 패턴 일치가 항상 지연됩니다. 사실, newtype을 사용하면 런타임시 랩핑이 더 이상 필요 없으며 패턴 일치는 실제로 no-op입니다.

+0

감사합니다. chi. 'data'에서'newtype'으로'Stream'을 바꾸는 것이 트릭을 만들었습니다. – ami