Haskell 프로덕션 코드에서 seq는 얼마나 자주 사용됩니까?


23

Haskell에서 작은 도구를 작성 한 경험이 있으며 특히 interact표준 입력을 처리하고 표준 출력으로 파이프하는 필터를 작성하는 데 매우 직관적 입니다.

최근에 평소보다 약 10 배 큰 파일에 이러한 필터를 사용하려고 시도했는데 Stack space overflow오류가 발생했습니다.

약간의 독서를 한 후에 (예를 들어 herehere ) 스택 공간을 절약하기위한 두 가지 지침을 확인했습니다 (경험이있는 Haskellers, 올바르지 않은 것을 쓰면 저를 정정하십시오).

  1. 꼬리 재귀가 아닌 재귀 함수 호출을 피하십시오 (꼬리 호출 최적화를 지원하는 모든 기능 언어에 유효).
  2. 소개 seq표현들이 감소되기 전에 너무 큰 성장하지 않도록 하위 표현의 초기 평가를 강제로 (이 게으른 평가를 사용하여 언어에 하스켈 특정, 또는 적어도이다).

seq내 코드에 5-6 번의 호출을 도입 한 후 툴이 원활하게 다시 실행됩니다 (더 큰 데이터에서도). 그러나 원래 코드는 조금 더 읽기 쉽습니다.

저는 숙련 된 Haskell 프로그래머가 아니기 때문에 seq이런 방식으로 소개 하는 것이 일반적인 관행인지, seqHaskell 프로덕션 코드에서 얼마나 자주 볼 수 있는지 묻고 싶었습니다 . 아니면 seq너무 자주 사용하지 않고 스택 공간을 거의 사용 하지 않는 기술이 있습니까?


1
설명 한 종류와 같은 최적화는 거의 항상 코드를 조금 덜 우아하게 만듭니다.
Robert Harvey

@Robert Harvey : 스택 사용량을 낮게 유지하는 다른 기술이 있습니까? 내 기능을 다르게 다시 작성해야한다고 생각하지만 잘 확립 된 기술이 있는지 여부는 알 수 없습니다. 첫 번째 시도는 꼬리 재귀 함수를 사용하여 내 문제를 완전히 해결할 수는 없었습니다.
Giorgio

답변:


17

불행히도 seq대용량 데이터에 대해 효율적이고 잘 작동하는 프로그램을 얻기 위해 사용해야하는 경우가 있습니다 . 따라서 대부분의 경우 프로덕션 코드에서 없이는 할 수 없습니다. Real World Haskell, 25 장. 프로파일 링 및 최적화 에서 자세한 정보를 찾을 수 있습니다 .

그러나 seq직접 사용하지 않는 방법이 있습니다. 이것은 코드를 더 깨끗하고 강력하게 만들 수 있습니다. 몇 가지 아이디어 :

  1. 대신 도관 , 파이프 또는 반복을 사용하십시오 interact. 게으른 IO는 메모리뿐만 아니라 리소스 관리에 문제가있는 것으로 알려져 있으며 이터 레이트는이를 극복하도록 정확하게 설계되었습니다. (데이터가 아무리 커도 게으른 IO를 함께 피하는 것이 좋습니다 . 게으른 I / O 문제를 참조하십시오 .)
  2. 엄격한 계산을 위해 설계된 foldl ' 또는 foldr' 또는 엄격한 버전의 라이브러리 (예 : Data.Map.Strict 또는 Control.Monad.State.Strict ) seq와 같은 결합기 를 직접 사용하거나 직접 설계하지 마십시오 .
  3. BangPatterns 확장을 사용하십시오 . seq엄격한 패턴 일치 로 대체 할 수 있습니다 . 엄격한 생성자 필드를 선언하는 것도 일부 경우에 유용 할 수 있습니다.
  4. 평가를 강제 하기 위해 전략 을 사용할 수도 있습니다 . 전략 라이브러리는 주로 병렬 계산을 목표로하지만 값을 WHNF ( rseq) 또는 전체 NF ( rdeepseq)로 강제하는 방법 도 있습니다. 컬렉션 작업, 전략 결합 등을위한 많은 유틸리티 방법이 있습니다.

+1 : 유용한 힌트와 링크에 감사드립니다. 포인트 3은 꽤 흥미로워 보입니다 (지금 가장 쉬운 솔루션). 제안 1과 관련하여 지연 IO를 피하는 것이 어떻게 개선 될 수 있는지 알지 못합니다. 지연 IO를 이해하는 한 (아마도 매우 긴) 데이터 스트림을 처리 해야하는 필터에 더 좋습니다.
Giorgio

2
@Giorgio 나는 Lazy IO의 문제에 대해 Haskell Wiki에 대한 링크를 추가했습니다. 지연 IO를 사용하면 리소스를 관리하는 데 매우 어려움을 겪을 수 있습니다. 예를 들어, 지연 평가로 인해 입력을 완전히 읽지 않으면 파일 핸들은 열린 상태로 유지됩니다 . 그리고 파일 핸들을 수동으로 이동하고 닫으면, 지연된 평가 판독으로 인해 지연되고 전체 입력을 읽기 전에 핸들을 닫는 경우가 종종 발생합니다. 그리고 게으른 IO의 메모리 문제를 피하는 것은 종종 어려운 일입니다.
Petr Pudlák

최근 에이 문제가 발생하여 프로그램에 파일 설명자가 부족합니다. 그래서 strict 사용하여 지연 IO를 엄격한 IO로 대체했습니다 ByteString.
조르지오
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.