박준규

@curry@hackers.pub · 271 following · 128 followers

darcs hub
hub.darcs.net/vincent
Hackage
hackage.haskell.org/user/JoonkyuPark
4
5

액티비티퍼브에 Place가 있어서 사람들이 위치 공유도 하고 장소에 ‘좋아요’도 누르듯이 Book도 있으면 재밌겠다. 사람들이 좋아하는 책에 ‘좋아요’도 누르고 서로 연결도 시켜주고!

액티비티퍼브에 Place가 있어서 사람들이 위치 공유도 하고 장소에 ‘좋아요’도 누르듯이 Book도 있으면 재밌겠다. 사람들이 좋아하는 책에 ‘좋아요’도 누르고 서로 연결도 시켜주고!

6

멘티를 서울숲하스켈에 보냈었는데, 거기갔다 왔더니 이제 JS 코드짤때 커링을 알아서 잘 활용한다. 사실 내가 그분께 주는 피드백이 '좀더 함수형으로 짜라' 이상도 이하도 아닌데(이거 들키면 안됨), 방법을 하나하나 가르치려니 너무 피곤해서 하스켈을 배우게 시켰다. 리턴 확실하구만.

1
3
4
0
0
0
0
2
1
0

저는 소셜 서비스의 핵심이 ‘좋아요(Like)’라고 생각합니다. 저는 제가 페이스북에서 처음으로 ‘좋아요’를 많이 받아서 너무 신났던 감정을 잊을 수 없습니다. 그리고 저는 지금도 ‘좋아요’의 노예⋯(사람들은 그런 너를 관종이라고 부른단다.)

actor가 object를 좋아한다는 의미의 관계를 나타낸 다이어그램. 'actor'와 'object'라는 두 개의 타원형 노드가 있고, 'Like'라는 레이블이 붙은 화살표가 'actor'에서 'object'로 향하고 있습니다.
7
1

액티비티 퍼브에 Place 타입이 아마도 트위터나 페이스북에서 글을 쓸 때 현재 위치를 남기는 용도인 것 같은데 장소에도 Like를 하면 재밌을 것 같은데 생각해보니 페이스북에 이미 있는 것 같다.

0
0
3

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

7
1
0
1
2
9

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 완전 무근본이었단건데, 이건 또 믿기 어렵다(하스켈의 설계 결정에 대한 신뢰 유지한다고 하면). 어디서 내가 잘못 파악한거지.

0

책 읽다가 생소한 게 나와서 적어 본다.

패키지 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 ByteStringByteString 청크 스트림을 표현한다. 이게 일종의 가변 상태를 가지고 있다. 이 가변 상태가 있기 때문에 앞에서 읽었지만 소모되지 않은 청크를 버리지 않고 입력에 다시 넣는 방식을 쓰는 것 같다.

이런 방식을 Incremental parsing이라고 하는 것 같다.

5
1
0
5
1
1
2
2

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

2
1

책 제목에 포함되어 있는 단어이자 패키지 이름인 pipes가 도대체 뭐하는 건지 감이 안 잡혔는데 드디어 해당 챕터에 돌입했다. 대충 보니 스트리밍 데이터를 처리하는 패키지인 것 같다. 라이브러리 제작자가 가브리엘라 님이라니!

‘스트리밍’이라는 단어를 많이 들어보고 많이 써왔는데 정확한 의미는 뭔지 몰랐다. 스트리밍은 큰 데이터를 잘라서 전달하는 것을 의미하는 것 같다.

https://hackage.haskell.org/package/pipes

2
2
2

책에 나온 예제를 따라 하는데 결과가 책과 달라 이상했다. 코드를 한참 보다가 결국 원인을 찾았다. 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을 리턴해야 하는데 반대로 적어버린 것이다. 덕분에 시간이 모자라서 남은 연습 문제 하나는 내일로 미뤄야겠다.

5

오늘 읽을 챕터 제목은 ‘스트리밍(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

“판타 레이”가 여기서 나온 말이구나. 나는 이 말을 웹툰 “덴마”에서 처음 봤다. 무슨 뜻인지도 모르고 봤네.

1
2

책 한 챕터 다 읽었다. 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
2
0
0

놀라서 전파하긴 했는데 살펴보니 어떤 분은 ‘아직 모른다’라고 하시는 분도 있네요. 구체적이고 정확한 후속 보도를 아시는 분은 공유를 부탁드립니다. 저도 확인해보겠습니다.