2012-12-19 2 views
1

의 일련의 엄격한 평가를 강제로 나는 다음과 같은 하스켈 타입 정의가 :방법 ByteString

import Data.Sequence(Seq, length) 
import Data.ByteString.UTF8(ByteString) 

type StringSeq = Seq ByteString 

내가 deepseq과 엄격한 평가를 강제하고자하는 유형 StringSeq의 표현이있다. 그래서 NFData의 인스턴스를 정의해야합니다.

import Control.DeepSeq(NFData, deepseq) 

instance NFData ByteString 

instance NFData a => NFData (Seq a) where 
    rnf s = rnf (length s) 

그래서 나는 순서 자체의 평가를 강제로 순서의 길이를 계산 : 나는 다음과 같은했다. 이것은 작동하는 것 같지만 이것이 올바른 구현입니까? 더 좋은 것들이 있습니까? 시퀀스의 길이를 계산하는 데 너무 많은 오버 헤드가 발생합니까?

+3

정의 할 수 있습니다. 확실히'NFData' 인스턴스는 유효하지 않습니다. 왜냐하면 Seq의 내용을 강요하려고 시도조차하지 않기 때문입니다. 또한'NFData'가 실제로 당신이 원하는 것일 가능성은 희박합니다. 너 정말하고 싶은게 뭐야? 'deepseq'는 보통 엄격한 동작 (및 성능)을 얻는 데 "너무 많이, 너무 늦음"입니다. – shachaf

+0

shachaf가 말한 것 외에도 이미 NFData 인스턴스가 있습니다 : 인스턴스 NFData a => NFData (Seq a) 여기서 rnf (Seq xs) = rnf xs'. (arrh,'containers' 만 7.6.1과 함께 나온다. 이전 버전은 아님) –

+1

하지만, Seq에 넣기 전에'ByteString'을'seq'하면된다. 'Seq'의 척추 엄격함으로 인해, 그것은 완벽한 평가를 보장합니다. –

답변

1

당신은 내가이 실제로 모나드 법칙을 따르는 생각하지 않는다

data Strict a = Strict {fromStrict :: !a} 
instance Monad Strict where 
    return = Strict 
    (Strict x) >>= f = f x 

좋아 엄격에 대한 모나드를 정의 할 수 있습니다, 그러나 충분히 가까운 거리에 있습니다. 이 당신이 기능을

srnf = Strict . rnf 

등이

instance NFData a => NFData (Seq a) where 
    rnf s = fromStrict $ (mapM srnf s) >> return() 

안된를 정의 할 수 있습니다 사용하지만, 작동합니다 (그리고 모든 Traversable 데이터 구조에 대한 작동합니다).

+0

나는 newtype Strict a = Strict {fromStrict :: a}'가 엄격하고 성능이 조금 더 좋을까 궁금하다. –

+0

'newtype'은 엄격하지 않습니다. 그것은 단지 존재하지 않습니다. 요점은'> ='의 정의에서의 패턴 매치는 신원 모나드가 그렇지 않을 때 평가를 강제한다는 것이다. 정의한 newtype을 사용할 수는 있지만'Strict x >> = f = seq x $ f x'라고해야합니다. –

1

계산 길이가 충분하지 않은 경우 시퀀스 내용의 일반 형식을 계산해야합니다. 모든 접이식 구조를 강제 설정할 수있는 seqFoldable (Control.Seq)을 사용하는 것이 좋습니다. 그럼 당신은 단순히

mySeq `using` seqFoldable rdeepseq 

를 호출하거나 'Seq` 이미 척추 엄격하기 때문에, 유용한 아무것도하지 않는 것`Seq`의 길이를 계산

instance NFData a => NFData (Seq a) where 
    rnf = seqFoldable rdeepseq 
관련 문제