오늘은 노는 날이니 짧게 쓰자. 요즘 하스켈 사용하면서 가장 많이 보이는 것이 많은 프로젝트에서 Prelude 대신 Relude를 사용한다는 점이다. Relude의 목표 중 하나가 생산성이기 때문에 팀원 분들에게 소개하고 프로젝트에 도입할 수 있을지 고민해보려고 한다. 지난번에도 언급한 Practical Web Development with Haskell에도 Prelude 대신 ClassyPrelude라고 하는 패키지를 사용하는 것을 보니 실용적인 서비스에서 대체로 Prelude 대신 사용하는 패키지를 사용하는 것 같다.
Relude는 하스켈 스타일 가이드로 검색했을 때 가장 먼저 나왔던 Kowainik이라고 하는 팀에서 만든 프로젝트이다.
문서도 잘 정리되어 있어 문서를 가볍게(아는 것만) 읽어보고 어떤 좋은 점이 있는지 살펴보자.
문서에 Relude를 프로젝트에 사용하는 방법이 여러 가지 나와 있지만 가장 쉬워 보이는 NoImplicitPrelude
언어 확장을 사용하는 방법으로 stack
프로젝트를 만들어 확인해보자.
package.yaml
에 relude
패키지 의존성을 추가하고 default-extensions
에 NoImplicitPrelude
를 추가하자.
default-extensions:
- NoImplicitPrelude
stack
이 기본으로 만들어 준 템플릿에서 Relude
기능을 몇 가지 확인해보자. 별 것은 아니지만 Prelude
를 다시 만든 패키지에서 가장 쓸모 있어 보이는 기능은 자주 사용하는 패키지를 Reexport
한 것이다. 그래서 Relude
만 import
해도 다음 패키지에 있는 각종 모듈을 바로 쓸 수 있다.
base
bytestring
containers
deepseq
ghc-prim
hashable
mtl
stm
text
transformers
unordered-containers
특히 mtl
, transformers
, text
, containers
같은 것은 자주 쓰고 있는데 Text
나 각종 모나드 트랜스포머 같은 것을 따로따로 import
하지 않고 써도 돼서 편리하다.
아마 탐구하는 대로 일기에 적으려고 하지만 deepseq
패키지도 reexport
되어 있다. 최근 하스켈 strict
와 lazy
에 대한 이해 부족 때문에 중첩된 데이터 구조에서 발생하는 예외를 테스트 코드에서 못 잡고 있었는데 아마도 지금 있는 데이터 구조에 NFData
인스턴스를 만들고 강제로 evaluation
하면 될 것으로 추측하고 있다.
두 번째로 undefined
가 있는 부분이 컴파일러 warning
처리되어 있다는 점이다. 하스켈은 타입을 먼저 작성하는 경우가 많아 구현을 undefined
로 남겨두는 경우가 많은데 실수로 구현을 깜빡하는 것을 예방해줄 수 있을 것 같다. 다음은 지금 쓰고 있는 VSCode 하스켈 확장을 설치하고 Relude
를 import
하고 undefined
를 사용해 본모습이다.
또 몇 가지 눈에 들어오는 점은 head
, tail
, init
, last
와 같은 리스트 함수가 빈 리스트일 때 예외가 발생하는데 안전을 위해 기본으로 빈 리스트에 쓸 수 없도록 하는 버전을 써야 한다.
head :: NonEmpty a -> a -- the first element of the list
tail :: NonEmpty a -> [a] -- the list without the first element
last :: NonEmpty a -> a -- the last element of the list
init :: NonEmpty a -> [a] -- the list without the last element
안전을 위한 기능은 몇 가지 또 있는데 read
도 타입 변환에 실패하면 역시 예외가 발생하는데 read
를 기본으로 쓸 수 없고 대신 readMaybe
를 기본으로 쓸 수 있다.
-- >>> readMaybe "1" :: Maybe Int
-- Just 1
그 외에도 sum
이나 product
함수를 strict
버전으로 쓰도록 해서 메모리 사용량을 줄이거나 error
함수가 Text
를 받을 수 있게 하는 버전(String
대신 Text
를 사용하는 것을 권장)등 여러 가지 유용한 기능이 있는 것 같다.
지금은 reexport
기능으로도 충분히 코드 크기를 줄일 수 있을 것 같아서 프로젝트에 도입해보자고 해야겠다.