엔드포인트 솔루션이나 네트워크 장비를 운영하다 보면 그 솔루션 본연의 역할을 지고지순(?) 하게 지키기보다는 뭔가 민원을 해결하는 예외 처리에 리소스를 투입할 때가 많은데 그럴 때마다 뭔가 법을 어긴 것 같고 마음이 안 좋다.

박준규
@curry@hackers.pub · 159 following · 73 followers
프로그래밍 언어 하스켈(Haskell) 덕질하는 계정
darcs hub
- hub.darcs.net/vincent
@curry박준규 이제 잘 될 겁니다!
@parameterfreak 님 어서 오세요!
@hongminhee洪 民憙 (Hong Minhee)
@parameterfreak 이분 계정이 다른 연합(우리.인생)에서 검색이 안 됩니다.
유심을 교체했다.
논리와 low-level data representation을 다뤄볼지, 아니면 함수형 추상 기계들(Turing Machine같은 것이지만 함수형을 위한 것들)을 다뤄볼지
@ailrunAilrun (UTC-5/-4) 저는 둘 다 궁금합니다.😀
https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.6#superclass-expansion-is-more-conservative
내가 9.4 -> 9.6 마이그레이션에서 겪고 있는 문제가 이거랑 관련이 있는거 같은데(확실치 않음)... 9.4에서는 c :: Type -> Constraint
일때 forall c. c Int
뭐 이런 조건이 있으면, 모든 c
에 대해 c Int
가 존재하는게 말이 안되는데도 실제로 c Int
꼴로 쓰이는 c
만 고려해서 타입체크를 통과시켜줬던거 같다(이것도 확실하지 않음). 근데 9.6에선 당연히 거부당한다.
위의 내 이해가 맞다면 9.4의 constraint solving 완전 무근본이었단건데, 이건 또 믿기 어렵다(하스켈의 설계 결정에 대한 신뢰 유지한다고 하면). 어디서 내가 잘못 파악한거지.
@bglbgl gwyng 어떤 코드에서 어떤 에러가 나나요?
책 읽다가 생소한 게 나와서 적어 본다.
패키지 attoparsec
에 있는 함수 parseOnly
는 청크 한 개만 다룰 수 있고 나머지 청크는 버린다. 이러면 스트림 데이터를 읽을 수가 없다. 이때 모듈 Data.Attoparsec.ByteString.Run
에 있는 다음 도구를 사용하면 된다.
parseAndRestore :: Monad m =>
RestorableInput m ByteString -> Parser a -> m (Either ParseError a)
data RestorbleInput m i = RestorableInput
(m i) -- ^ Get the next chunk of input, or an empty string if there is no more
(i -> m ()) -- ^ Push a nonempty chunk of input back to the input stream
newRestorableIO
:: IO i -- ^ Get the next chunk of input, or an empty string if there is no more
-> IO (RestorableInput IO i)
RestorableInput IO ByteString
은 ByteString
청크 스트림을 표현한다. 이게 일종의 가변 상태를 가지고 있다. 이 가변 상태가 있기 때문에 앞에서 읽었지만 소모되지 않은 청크를 버리지 않고 입력에 다시 넣는 방식을 쓰는 것 같다.
이런 방식을 Incremental parsing이라고 하는 것 같다.
그냥 커피랑 간식만 먹다가 왔다. package.yaml 잘못 수정한거랑 constructor import 빼먹은거 고쳐드린게 전부.
RE: https://hackers.pub/@bgl/01965764-69ba-7e46-934f-ab8450c2486c
@bglbgl gwyng 몰래 Nix 영업은 안 하셨나요?
이제 서울하스켈숲 세미나 조교하러 간다
@bglbgl gwyng 고생이 많으십니다! 세미나는 어떤가요?
와, 이번 장에서는 ExceptT
모나드 트랜스포머를 알려준다! 크리스와 줄리 선생님 필력만 믿습니다.
https://hackage-content.haskell.org/package/transformers-0.6.2.0/docs/Control-Monad-Trans-Except.html
역시 애플리케이션 만드는 것보다 라이브러리 만드는 게 더 재밌는 것 같다. 다들 이럴까, 내가 유독 그런 걸까?
@hongminhee洪 民憙 (Hong Minhee) 애플리케이션은 UI 때문에⋯
거의 15년 전에 야심 넘치게 Benjamin C. Pierce의 Types and Programming Languages를 한 권 장만했지만 아직도 아주 깨끗하다. 앞으로도 읽을 일이 없을 것 같다… ㅋㅋㅋ
@hongminhee洪 民憙 (Hong Minhee) 앗, 전설의(?) 책 tapl을 갖고 계시다니! 저는 그 책 너무 비싸서 도서관에서 잠깐 열람만 했었어요.
하스켈 패키지 서버 에러 나서 라이브러리 문서를 못보니까 코딩을 못하네!
모든 파싱 라이브러리가 스트리밍을 지원하는 건 아니구나. Attoparsec은 스트리밍 데이터를 파싱할 수 있다고 한다. https://hackage.haskell.org/package/attoparsec
For my library and CLI projects, I've been writing documentation before writing any code. It helps me imagine the final interface early on, which usually leads to better design. Sure, sometimes I miss implementation details and have to revise later, but hey—it's just docs. Docs are easy to change.
This tiny habit has surprisingly big payoffs. When I focus on how things will be used rather than how they'll be built, I end up with interfaces that actually make sense.
Anyone else do this? Curious about your experience with documentation-first approaches.
RE: https://hollo.social/@hongminhee/01964c76-ef1e-7994-b3f0-57f967742566
@hongminhee洪 民憙 (Hong Minhee) Document Driven Development!
어제는 결국 그냥 잤다… ㅋㅋㅋ
@hongminhee洪 民憙 (Hong Minhee) 잘하셨습니다! 휴식이 중요하죠. 왠지 인기 웹툰의 독자가 댓글로 작가를 응원하는 마음으로 민희 님의 건강을 응원하게 됩니다.
책 제목에 포함되어 있는 단어이자 패키지 이름인 pipes
가 도대체 뭐하는 건지 감이 안 잡혔는데 드디어 해당 챕터에 돌입했다. 대충 보니 스트리밍 데이터를 처리하는 패키지인 것 같다. 라이브러리 제작자가 가브리엘라 님이라니!
‘스트리밍’이라는 단어를 많이 들어보고 많이 써왔는데 정확한 의미는 뭔지 몰랐다. 스트리밍은 큰 데이터를 잘라서 전달하는 것을 의미하는 것 같다.
ChatGPT도 루비 태그를 지원하면 좋겠다!
@bglbgl gwyng miniKanren이라는 게 있고 다른 언어로 여러 구현체가 있나 봅니다. kanren은 일본어 関連의 발음을 영어로 적은 거네요. 공교롭게 하스켈 커뮤니티에서도 최근 typedKanren을 다룬 글이 있길래 잠깐 찾아봤습니다.
https://discourse.haskell.org/t/the-haskell-unfolder-episode-42-logic-programming-with-typedkanren/11869
책에 나온 예제를 따라 하는데 결과가 책과 달라 이상했다. 코드를 한참 보다가 결국 원인을 찾았다. if 분기의 결과를 반대로 적었던 것이다.
repeatUntil
:: Monad m
=> m chunk
-> (chunk -> Bool)
-> (chunk -> m ())
-> m ()
repeatUntil getChunk isEnd f =
repeatUntilNothing getChunkMaybe f
where
getChunkMaybe = do
chunk <- getChunk
if isEnd chunk
then return (Just chunk)
else return Nothing
청크가 없으면 Nothing
을 리턴해야 하는데 반대로 적어버린 것이다. 덕분에 시간이 모자라서 남은 연습 문제 하나는 내일로 미뤄야겠다.
오늘 읽을 챕터 제목은 ‘스트리밍(Streaming)’이다. 서두에 이런 말이 나온다.
No one ever steps in the same stream twice, for it is not the same stream and they are not the same person.
ChatGPT에게 저게 유명한 말인지 물었더니 다음과 같이 대답했다.
https://chatgpt.com/share/6800e63e-07b4-800c-b32b-fef1723ef5c5
“판타 레이”가 여기서 나온 말이구나. 나는 이 말을 웹툰 “덴마”에서 처음 봤다. 무슨 뜻인지도 모르고 봤네.
.o0(그냥 이거 튜링의사과 대관하면 되겠네)
@kodingwarriorJaeyeol Lee (a.k.a. kodingwarrior)
《오픈소스로 미래를 연마하라》(인사이트, 2019)에 고민하시는 내용이 일부 소개되어 있는 거 같습니다. 특히 181쪽에 나오는 ‘콘퍼런스나 모임에서 대처 팁’이 도움이 될 것 같아요.
책 한 챕터 다 읽었다. stm
패키지에서 제공하는 기능이 많지만 여기서는 TVar
만 쓸 줄 알면 돼서 분량이 많지 않네. 다음과 같은 형식으로 웹사이트 방문자 카운터를 구현할 수 있다.
countingServer :: IO ()
countingServer = do
hitCounter <- atomically (newTVar @Natural 0)
serve @IO HostAny "8000" \(s, _) -> do
count <- atomically (increment hitCounter)
sendResponse s (textOk (countHelloText count))
increment :: TVar Natural -> STM Natural
increment hitCounter = do
oldCount <- readTVar hitCounter
let newCount = oldCount + 1
writeTVar hitCounter newCount
return newCount
ChatGPT에 문제가 생긴 것 같다. 접속이 안 되네.
이제 된다.
ChatGPT에 문제가 생긴 것 같다. 접속이 안 되네.
놀라서 전파하긴 했는데 살펴보니 어떤 분은 ‘아직 모른다’라고 하시는 분도 있네요. 구체적이고 정확한 후속 보도를 아시는 분은 공유를 부탁드립니다. 저도 확인해보겠습니다.

CISA extends funding to ensure 'no lapse in critical CVE services'
CISA says the U.S. government has extended funding to ensure no continuity issues with the critical Common Vulnerabilities and Exposures (CVE) program.
www.bleepingcomputer.com · BleepingComputer
Link author: Sergiu Gatlan@serghei@mastodon.social
놀라서 전파하긴 했는데 살펴보니 어떤 분은 ‘아직 모른다’라고 하시는 분도 있네요. 구체적이고 정확한 후속 보도를 아시는 분은 공유를 부탁드립니다. 저도 확인해보겠습니다.
@kodingwarriorJaeyeol Lee 방금 배포했습니다. ㅋㅋㅋ
@curry박준규 근데 따지고보면 하스켈도 문법 복잡하죠. 각각 다 역할이 있어서 그렇지만요.
@bglbgl gwyng 이게 생각해보니 ‘문법이 복잡하다’, ‘문법 요소가 적다’라는 표현이 구체적이지 않은 것 같습니다. 갑자기 언어 확장이 떠오르면서 ‘문법 안 복잡한 거 맞나?’ 싶네요. 그래서 표현을 좀 바꾸면 저는 사전에 정의된 키워드가 적을 수록 좋다고 생각합니다.
GHCup에서 GHC의 추천 버전이 9.6.7로 변경되었다. 내 로컬에서 버전 올려도 문제 없으려나!
✗ ghc 9.6.7 recommended,base-4.18.3.0
https://github.com/haskell/ghcup-metadata/pull/304
한편 현재 최신 버전은 9.12.2이다.
✗ ghc 9.12.2 latest,base-4.21.0.0 2025-03-12
하스켈에서 $
가 infix operator가 아니라 문법 요소여야 한다는 얘기에는 동의하는 사람들이 꽤 있다. 근데 1 + $ 2 + 3
도 1 + (2 + 3)
으로 변환되어야 한다고 하면 다들 싫어한다ㅋㅋ 근데 나는 저것도 좋다고 본다.
@bglbgl gwyng 한편 저는 문법 요소가 가능한 적어야 좋다고 생각합니다. 그래서 하스켈을 처음 봤을 때
Bool
이 라이브러리인 게 좋았어요.
data Bool = False | True
@curry박준규
@lionhairdino 종료 코드(Exit code)가 0이 아닐 때는 실패하는 방식이 없나요? Emacs는 그런 식으로 도니 Vim에도 있을법 한데...
@ailrunAilrun (UTC-5/-4)
@lionhairdino Vim에 그런 방식은 없는 것 같습니다. 대신
v:shell_error
를 검사해서 종료 코드가 0이 아닐 때는 명령을 실행하지 않는 코드를 작성하거나 autocmd
를 사용하면 된다고 하네요.(ChatGPT가)
한편 종료 코드를 확인하는 방법을 처음 알았습니다.
echo $?
자기 전에 그래도 한 챕터를 다 읽고 연습 문제까지 풀었다. 다음 챕터부터는 그 유명한 STM을 다룬다!
@curry박준규 보통 HLS에 붙어 있는 것 쓰는데, 그리 단독으로도 쓰는 군요. 근데, 코드를 지운다니 살짝 무서운데요.
@lionhairdino
:%!foo
가 파일의 전체 내용을 foo
의 출력으로 대체하는 방식이다 보니 그런 것 같습니다.
Vim에서 첫 행으로 갈 때 매번 1G
했는데 그냥 gg
하면 된다니!
하스켈 코드 포매터 stylish-haskell
을 잘 쓰고 있습니다. Vim에서 :%!stylish-haskell
이라고 입력하는 방식으로 사용하는데요, 코드에 문제가 있을 경우 코드 전체가 지워지고 다음과 같은 문자열로 대체됩니다.
<string>:1:18: error: [GHC-58481] parse error on input `!'
Vim에서 작업 중이므로 단순히 u
를 눌러서 취소하면 되긴 합니다만 혹시 다른 방법이 있을까요?
패키지 문서를 읽다가 Vim에 :set formatprg
와 gq
라는 게 있다는 걸 알았습니다. 이제 굳이 :%!foo
하지 않아도 되겠어요.
https://github.com/haskell/stylish-haskell?tab=readme-ov-file#vim-integration
하스켈 코드 포매터 stylish-haskell
을 잘 쓰고 있습니다. Vim에서 :%!stylish-haskell
이라고 입력하는 방식으로 사용하는데요, 코드에 문제가 있을 경우 코드 전체가 지워지고 다음과 같은 문자열로 대체됩니다.
<string>:1:18: error: [GHC-58481] parse error on input `!'
Vim에서 작업 중이므로 단순히 u
를 눌러서 취소하면 되긴 합니다만 혹시 다른 방법이 있을까요?
curl --http1.1 --dump-header - http://localhost:8000
--http1.1
처럼 버전을 정할 수 있다.--dump-header <filename>
으로 헤더를 파일로 저장할 수 있는데 파일 이름 대신-
를 적으면 헤더를 화면에 출력한다.
책[1]에서 문자열을 다룰 때 StrictText
와 Builder
의 성능을 비교하는 예제에서 Builder
의 성능이 더 좋다고 설명한다. 그런데 내 PC에서 같은 코드를 실행했는데 결과가 반대로 나왔다. 이상해서 문자열 길이를 늘렸더니 책에서 말한대로 나왔다.
ghci> concatSpeedTest 50000
0.004451s
0.04721s
ghci> concatSpeedTest 500000
0.062405s
0.023449s
ghci> concatSpeedTest 5000000
0.511402s
0.205632s
Chris Martin, Julie Moronuki, 《Sockets and Pipes》 ↩︎
Yacc와 같은 파서 제네레이터에 BNF를 넣으면 파서 코드가 자동으로 생성된다. 그런데 HTTP나 ActivityPub 등의 프로토콜 스펙을 입력으로 넣으면 자동으로 코드를 구현해주는 도구 어디 없나?
오, Quasi-quotation 신기하다. 문자열 안에 아스키 글자를 넣으면 컴파일 에러가 나네!
library/Book.hs:221:18: error:
• Must be only ASCII characters.
• In the quasi-quotation: [A.string|GET ♫ HTTP/1.1|]
|
221 | line [A.string|GET ♫ HTTP/1.1|] <>
| ^^^^^^^^^^^^^^^^
‘아스키 글자가 아닌 것’이라고 적어야 하는데 잘못 적었네.
오, Quasi-quotation 신기하다. 문자열 안에 아스키 글자를 넣으면 컴파일 에러가 나네!
library/Book.hs:221:18: error:
• Must be only ASCII characters.
• In the quasi-quotation: [A.string|GET ♫ HTTP/1.1|]
|
221 | line [A.string|GET ♫ HTTP/1.1|] <>
| ^^^^^^^^^^^^^^^^
HTTP 요청에서 이름과 값의 쌍을 필드(fields)라고 부르는구나!
HTTP를 다룬 RFC 중 2022년에 9110과 9112가 나오면서 1999년에 나온 2616과 2014년에 나온 7230은 쓸모없어졌다고 한다.