@bglbgl gwyng 사이먼 페이튼 존스의 고양이 이름이 하스켈인데 고양이 이름이 먼저였을까요, 프로그래밍 언어 이름이 먼저였을까요?

bgl gwyng
@bgl@hackers.pub · 64 following · 64 followers
슈티를 함께 만들 팀을 만들고 있습니다. 관심 있으신 분, 또는 잘 모르겠지만 이야기를 나눠보고 싶은 분도 bgl@gwyng.com으로 편하게 연락주세요.
GitHub
- @bglgwyng
shootee
- www.shootee.io
@curry박준규 처음 알았네요ㅋㅋ 이경우는 공통조상?이 짐작되긴 하죠
높은 목표를 가진 개발자라도 결국엔 아주 사소한 동기로 움직이는거 같다.
나같은 경우엔, 완벽한 프로그래밍 언어를 만드는 것이 목표인데(가능한지는 차치하고), 완벽하다는건 나말고 다른 누군가가 같은 문제 의식을 가진다면 똑같이 그곳에 다다를 거란걸 의미한다. 그 프로그래밍 언어의 설계에서 내 마음대로 결정할수 있는 부분은 없을 것이다. 설계에서 최적의 선택지만을 택해야 완벽할테니까 말이다. 그때가선 그 선택들이 너무 자명해서, 내겐 처음부터 선택의 여지가 없었다고 느낄것이다.
그럼에도 내가 결정할 수 있을 부분이 있기는한데, 그 언어의 이름에 뜬금없이 우리집 강아지 이름을 붙인다던가 하는 것이다. 이게 그 사소한 동기다.
디지털 가드닝에 관심이 많은 개발자입니다.
- 특히 위키 형식의 문서 관리, knowledge graph 구조의 시각화에 관심이 있어요.
- kodingwarrior.github.io/wiki
Neovim 이라는 텍스트 에디터에 굉장히 꽂혀있습니다.
- 과몰입한 나머지 플러그인까지 개발해본 경험이 있어요.
- 한국어권 개발자를 위한 Vim 디스코드를 운영중입니다 (vim.kr)
프로그래밍을 하는 행위 자체를 좋아합니다.
- 프로그래밍으로 퍼즐을 푸는 행위를 좋아했고, 비슷한 흔적을 가진 사람들에게 친밀감을 느낍니다.
정말... 로컬에서 마이크로커밋 하라면서 정작 스쿼시로 날려버릴 때 “왜??????????” 라고 생각한 적이 있다.
https://hackers.pub/@bgl/0195bda7-f18d-72eb-8933-81e819715410
해커펍은 퍼머링크로 아카이빙 참조하기 최적이라 생각해서 앞으로 기술을 다루며 기록 및 참조하는 용도로 잘 사용하려고 합니다.
트위터는 나중에 다른 사람에게 보여줄 참조용으로 쓰기에는 너무 정보 대비 소음이 많은 특성 때문에 잘 맞지 않는다고 생각합니다.
그동안(10+년;;) git이 엄청 잘만든 물건 같지는 않다고 생각하며 대충 쓰고있었는데, 요즘 branch 개념 자체가 근본적인 실수란 생각이 들기 시작했다. branch 대신에 변경의 시작과 끝, 양 끝점을 가지는 interval을 쓰는게 맞는거 같다(카테고리 이론의 작은 교훈: primitive는 양 끝점을 가지는게 좋다).
git을 쓰면 히스토리 길어진다고 squash merge 등을 하는데, (나도 하지만) 사실 기껏 만들어놓은 히스토리를 뭉개버리는 말도 안되는 동작이다. 만약 interval을 쓴다면 히스토리는 그대로 남기고 UI 단에서 fold/unfold 등을 해줄수 있을 것이다.
Darcs 등이 interval에 기초하는데, 지금은 일이 너무 바빠서 시도할 여유가 없다. 한번 숨고를 시간이 주어지면 멀쩡한 VCS를 탐색하는 시간을 가질것이다.
📢 Hackers' Pub 초대 시스템 오픈!
Hackers' Pub에 초대 시스템이 적용되었습니다. 이제 설정 → 초대 페이지에서 지인들을 초대할 수 있습니다.
주요 내용:
- 초대장 3장 지급: 기존 회원분들께 3장의 초대장이 지급되었습니다.
- 초대 방법: 설정 → 초대 페이지에서 초대 링크를 생성하여 공유하거나, 이메일 주소를 입력하여 초대할 수 있습니다.
- 추가 초대: 초대장은 향후 비정기적으로 추가될 예정입니다.
- 자동 팔로: 초대자와 피초대자는 자동으로 상호 팔로됩니다. (언팔로 가능.)
Hackers' Pub의 퀄리티를 유지하고, 더욱 풍성한 기술 논의를 위해 신중한 초대를 부탁드립니다.
궁금한 점이나 건의사항은 답글로 남겨주세요.
Hackers' Pub 커뮤니티 성장에 많은 참여 부탁드립니다!
hackers.pub 로그인 페이지에서,
가입하려 이메일을 넣었더니, 베타 서비스라 안된다는 메시지가 뜹니다. 음, 제 생각엔 이 메시지는 로그인 폼에 뭔가를 입력하기 전에 나오는 게 더 부드럽지 않을까 싶어요.
#HackersPub
https://github.com/dahlia/hackerspub/pull/12
해커스펍의 멘션 기능에 가독성 개선이 필요할 것 같아서 제안하는 느낌으로 PR은 올렸는데, 다른 분들도 어떤 의견을 가지고 계실지 모르겠다
나와주시는 한 분 한 분 너무 감사하게 생각하고, 비상행동은 언제든지 광장을 열기 위해서 계속해서 노력을 해나갈 테니까 함께, 끝까지 함께 해주셨으면 좋겠다 이런 말씀을 드리고 싶습니다."
@curry박준규 확장이 하도 많아서 뭐가 있는지 다 알기가 어려운 것 같아요… 😂
@hongminhee洪 民憙 (Hong Minhee) 이런 표현이 있습니다.
GHC has more flags than the UN.
타입스크립트에 있었으면 좋겠음
@tirr티르 저도 서브타이핑 기반인 TS에 상대적으로 쉽게 도입할 기능이 https://github.com/microsoft/TypeScript/issues/13219 이렇게 오랫동안 진행안되는게 불만입니다. 막상 TS 이펙트 라이브러리들은
|
로 흉내내서 잘 쓰고 있더라고요. Haskell처럼 대수적 이펙트는 구현할수있지만 서브타이핑 기반은 아닌 언어에선, 서브타이핑 흉내낸다고 타입레벨 차력쇼하고 있는데 맞는 방향인지 모르겠습니다.
@hongminhee洪 民憙 (Hong Minhee) I can't agree more. 'Java sucks' doesn't apply here at least. Subtyping plays really well in unioning error types.
@bglbgl gwyng Absolutely! You make a great point about subtyping—it's one of Java's underappreciated strengths for error handling. The exception hierarchy lets you catch specific exceptions or their broader subtypes as needed, giving you flexible error composition without extra syntax.
bgl gwyng shared the below article:
Revisiting Java's Checked Exceptions: An Underappreciated Type Safety Feature

洪 民憙 (Hong Minhee) @hongminhee@hackers.pub
Despite their bad reputation in the Java community, checked exceptions provide superior type safety comparable to Rust's Result<T, E>
or Haskell's Either a b
—we've been dismissing one of Java's best features all along.
Introduction
Few features in Java have been as consistently criticized as checked exceptions. Modern Java libraries and frameworks often go to great lengths to avoid them. Newer JVM languages like Kotlin have abandoned them entirely. Many experienced Java developers consider them a design mistake.
But what if this conventional wisdom is wrong? What if checked exceptions represent one of Java's most forward-thinking features?
In this post, I'll argue that Java's checked exceptions were ahead of their time, offering many of the same type safety benefits that are now celebrated in languages like Rust and Haskell. Rather than abandoning this feature, we should consider how to improve it to work better with modern Java's features.
Understanding Java's Exception Handling Model
To set the stage, let's review how Java's exception system works:
-
Unchecked exceptions (subclasses of
RuntimeException
orError
): These don't need to be declared or caught. They typically represent programming errors (NullPointerException
,IndexOutOfBoundsException
) or unrecoverable conditions (OutOfMemoryError
). -
Checked exceptions (subclasses of
Exception
but notRuntimeException
): These must either be caught withtry
/catch
blocks or declared in the method signature withthrows
. They represent recoverable conditions that are outside the normal flow of execution (IOException
,SQLException
).
Here's how this works in practice:
// Checked exception - compiler forces you to handle or declare it
public void readFile(String path) throws IOException {
Files.readAllLines(Path.of(path));
}
// Unchecked exception - no compiler enforcement
public void processArray(int[] array) {
int value = array[array.length + 1]; // May throw ArrayIndexOutOfBoundsException
}
The Type Safety Argument for Checked Exceptions
At their core, checked exceptions are a way of encoding potential failure modes into the type system via method signatures. This makes certain failure cases part of the API contract, forcing client code to explicitly handle these cases.
Consider this method signature:
public byte[] readFileContents(String filePath) throws IOException
The throws IOException
clause tells us something critical: this method might fail in ways related to IO operations. The compiler ensures you can't simply ignore this fact. You must either:
- Handle the exception with a try-catch block
- Propagate it by declaring it in your own method signature
This type-level representation of potential failures aligns perfectly with principles of modern type-safe programming.
Automatic Propagation: A Hidden Advantage
One often overlooked advantage of Java's checked exceptions is their automatic propagation. Once you declare a method as throws IOException
, any exception that occurs is automatically propagated to the caller without additional syntax.
Compare this with Rust, where you must use the ?
operator every time you call a function that returns a Result
:
// Rust requires explicit propagation with ? for each call
fn read_and_process(path: &str) -> Result<(), std::io::Error> {
let content = std::fs::read_to_string(path)?;
process_content(&content)?;
Ok(())
}
// Java automatically propagates exceptions once declared
void readAndProcess(String path) throws IOException {
String content = Files.readString(Path.of(path));
processContent(content); // If this throws IOException, it's automatically propagated
}
In complex methods with many potential failure points, Java's approach leads to cleaner code by eliminating the need for repetitive error propagation markers.
Modern Parallels: Result Types in Rust and Haskell
The approach of encoding failure possibilities in the type system has been adopted by many modern languages, most notably Rust with its Result<T, E>
type and Haskell with its Either a b
type.
In Rust:
fn read_file_contents(file_path: &str) -> Result<Vec<u8>, std::io::Error> {
std::fs::read(file_path)
}
When calling this function, you can't just ignore the potential for errors—you need to handle both the success case and the error case, often using the ?
operator or pattern matching.
In Haskell:
readFileContents :: FilePath -> IO (Either IOException ByteString)
readFileContents path = try $ BS.readFile path
Again, the caller must explicitly deal with both possible outcomes.
This is fundamentally the same insight that motivated Java's checked exceptions: make failure handling explicit in the type system.
Valid Criticisms of Checked Exceptions
If checked exceptions are conceptually similar to these widely-praised error handling mechanisms, why have they fallen out of favor? There are several legitimate criticisms:
1. Excessive Boilerplate in the Call Chain
The most common complaint is the boilerplate required when propagating exceptions up the call stack:
void methodA() throws IOException {
methodB();
}
void methodB() throws IOException {
methodC();
}
void methodC() throws IOException {
// Actual code that might throw IOException
}
Every method in the chain must declare the same exception, creating repetitive code. While automatic propagation works well within a method, the explicit declaration in method signatures creates overhead.
2. Poor Integration with Functional Programming
Java 8 introduced lambdas and streams, but checked exceptions don't play well with them:
// Won't compile because map doesn't expect functions that throw checked exceptions
List<String> fileContents = filePaths.stream()
.map(path -> Files.readString(Path.of(path))) // Throws IOException
.collect(Collectors.toList());
This forces developers to use awkward workarounds:
List<String> fileContents = filePaths.stream()
.map(path -> {
try {
return Files.readString(Path.of(path));
} catch (IOException e) {
throw new UncheckedIOException(e); // Wrap in an unchecked exception
}
})
.collect(Collectors.toList());
3. Interface Evolution Problems
Adding a checked exception to an existing method breaks all implementing classes and calling code. This makes evolving interfaces over time difficult, especially for widely-used libraries and frameworks.
4. Catch-and-Ignore Anti-Pattern
The strictness of checked exceptions can lead to the worst possible outcome—developers simply catching and ignoring exceptions to make the compiler happy:
try {
// Code that might throw
} catch (Exception e) {
// Do nothing or just log
}
This is worse than having no exception checking at all because it provides a false sense of security.
Improving Checked Exceptions Without Abandoning Them
Rather than abandoning checked exceptions entirely, Java could enhance the existing system to address these legitimate concerns. Here are some potential improvements that preserve the type safety benefits while addressing the practical problems:
1. Allow lambdas to declare checked exceptions
One of the biggest pain points with checked exceptions today is their incompatibility with functional interfaces. Consider how much cleaner this would be:
// Current approach - forced to handle or wrap exceptions inline
List<String> contents = filePaths.stream()
.map(path -> {
try {
return Files.readString(Path.of(path));
} catch (IOException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());
// Potential future approach - lambdas can declare exceptions
List<String> contents = filePaths.stream()
.map((String path) throws IOException -> Files.readString(Path.of(path)))
.collect(Collectors.toList());
This would require updating functional interfaces to support exception declarations:
@FunctionalInterface
public interface Function<T, R, E extends Exception> {
R apply(T t) throws E;
}
2. Generic exception types in throws clauses
Another powerful enhancement would be allowing generic type parameters in throws
clauses:
public <E extends Exception> void processWithException(Supplier<Void, E> supplier) throws E {
supplier.get();
}
This would enable much more flexible composition of methods that work with different exception types, bringing some of the flexibility of Rust's Result<T, E>
to Java's existing exception system.
3. Better support for exception handling in functional contexts
Unlike Rust which requires the ?
operator for error propagation, Java already automatically propagates checked exceptions when declared in the method signature. What Java needs instead is better support for checked exceptions in functional contexts:
// Current approach for handling exceptions in streams
List<String> contents = filePaths.stream()
.map(path -> {
try {
return Files.readString(Path.of(path));
} catch (IOException e) {
throw new RuntimeException(e); // Lose type information
}
})
.collect(Collectors.toList());
// Hypothetical improved API
List<String> contents = filePaths.stream()
.mapThrowing(path -> Files.readString(Path.of(path))) // Preserves checked exception
.onException(IOException.class, e -> logError(e))
.collect(Collectors.toList());
4. Integration with Optional<T>
and Stream<T>
APIs
The standard library could be enhanced to better support operations that might throw checked exceptions:
// Hypothetical API
Optional<String> content = Optional.ofThrowable(() -> Files.readString(Path.of("file.txt")));
content.ifPresentOrElse(
this::processContent,
exception -> log.error("Failed to read file", exception)
);
Comparison with Other Languages' Approaches
It's worth examining how other languages have addressed the error handling problem:
Rust's Result<T, E>
and ?
operator
Rust's approach using Result<T, E>
and the ?
operator shows how propagation can be made concise while keeping the type safety benefits. The ?
operator automatically unwraps a successful result or returns the error to the caller, making propagation more elegant.
However, Rust's approach requires explicit propagation at each step, which can be more verbose than Java's automatic propagation in certain scenarios.
Kotlin's Approach
Kotlin made all exceptions unchecked but provides functional constructs like runCatching
that bring back some type safety in a more modern way:
val result = runCatching {
Files.readString(Path.of("file.txt"))
}
result.fold(
onSuccess = { content -> processContent(content) },
onFailure = { exception -> log.error("Failed to read file", exception) }
)
This approach works well with Kotlin's functional programming paradigm but lacks compile-time enforcement.
Scala's Try[T]
, Either[A, B]
, and Effect Systems
Scala offers Try[T]
, Either[A, B]
, and various effect systems that encode errors in the type system while integrating well with functional programming:
import scala.util.Try
val fileContent: Try[String] = Try {
Source.fromFile("file.txt").mkString
}
fileContent match {
case Success(content) => processContent(content)
case Failure(exception) => log.error("Failed to read file", exception)
}
This approach preserves type safety while fitting well with Scala's functional paradigm.
Conclusion
Java's checked exceptions were a pioneering attempt to bring type safety to error handling. While the implementation has shortcomings, the core concept aligns with modern type-safe approaches to error handling in languages like Rust and Haskell.
Copying Rust's Result<T, E>
might seem like the obvious solution, but it would represent a radical departure from Java's established paradigms. Instead, targeted enhancements to the existing checked exceptions system—like allowing lambdas to declare exceptions and supporting generic exception types—could preserve Java's unique approach while addressing its practical limitations.
The beauty of such improvements is that they'd maintain backward compatibility while making checked exceptions work seamlessly with modern Java features like lambdas and streams. They would acknowledge that the core concept of checked exceptions was sound—the problem was in the implementation details and their interaction with newer language features.
So rather than abandoning checked exceptions entirely, perhaps we should recognize them as a forward-thinking feature that was implemented before its time. As Java continues to evolve, we have an opportunity to refine this system rather than replace it.
In the meantime, next time you're tempted to disparage checked exceptions, remember: they're not just an annoying Java quirk—they're an early attempt at the same type safety paradigm that newer languages now implement with much celebration.
What do you think? Could these improvements make checked exceptions viable for modern Java development? Or is it too late to salvage this controversial feature? I'm interested in hearing your thoughts in the comments.
uv2nix는 uv보다 구리고, cabal2nix는 cabal보다 구린데, Nix는 uv + cabal + ... 보다 낫다. Nix 커뮤니티를 키우려면, 후자를 이해시키고(쉬움) 전자에 대해 익스큐즈하도록 설득해야한다(어려움) .
Hot take: Despite their bad reputation in the Java community, checked exceptions provide superior type safety comparable to Rust's Result<T, E>
or Haskell's Either a b
—we've been dismissing one of Java's best features all along.
@hongminhee洪 民憙 (Hong Minhee) I can't agree more. 'Java sucks' doesn't apply here at least. Subtyping plays really well in unioning error types.
@bglbgl gwyng 갑자기 딴 이야기긴 한데,
@bglbgl gwyng 님은 Haskell 툴체인으로 Stack 쓰시나요, 아니면 Cabal 쓰시나요? 몇 년 전부터 Stack을 썼는데 요즘엔 Stack 쪽이 개발이 잘 안 되는 것 같아서 다시 Cabal로 넘어가야 하나 고민하고 있거든요…
@hongminhee洪 民憙 (Hong Minhee) 저는 Nix를 쓰고 있습니다. 한동안 Haskell 안쓰고있다가 오랜만에 돌아왔더니 다들 Nix 쓰고있어서 그냥 따라 쓰는 상태입니다. Nix가 해결하려는 문제와 방향은 공감하지만, Haksell + Nix가 막 엄청 좋은지는 잘 모르겠는 상태에요.
Nix로 그냥 GHC랑 Cabal, Stack 버전만 잡고 나머지는 Cabal, Stack 등의 기존 하스켈 툴링에 맡기는 방법이 있고, 또 Nix가 패키지 다운받아서 빌드하는 역할까지 대신해버리는 방법이 있는데, 제가 쓰고 있는 방법은 후자입니다.
모든 자바스크립트 개발자들이 단 하나의 패키지 매니저와 단 하나의 빌드 시스템, 단 하나의 모듈 시스템을 사용하면 좋겠다고 진심으로 생각한다
@parksbSimon Park 어디는 망치가 너무 많아서 문제고 어디는 너무 적어서 문제죠ㅋㅋ
모든 자바스크립트 개발자들이 단 하나의 패키지 매니저와 단 하나의 빌드 시스템, 단 하나의 모듈 시스템을 사용하면 좋겠다고 진심으로 생각한다
C++ 표준화 위원회(WG21)에게 C++의 원 저자인 비야네 스트롭스트룹Bjarne Stroustrup이 보낸 메일이 이번 달 초에 본인에 의해 공개된 모양이다. C++가 요즘 안전하지 않은 언어라고 열심히 얻어 맞고 있는 게 싫은지 프로파일(P3081)이라고 하는 언어 부분집합을 정의하려고 했는데, 프로파일이 다루는 문제들이 아주 쉬운 것부터 연구가 필요한 것까지 한데 뒤섞여 있어 구현이 매우 까다롭기에 해당 제안이 적절하지 않음을 올해 초에 가멸차게 까는 글(P3586)이 올라 오자 거기에 대한 응답으로 작성된 것으로 보인다. 더 레지스터의 표현을 빌면 "(본지가 아는 한) 스트롭스트룹이 이 정도로 강조해서 말하는 건 2018년 이래 처음"이라나.
여론은 당연히 호의적이지 않은데, 기술적인 반론이 대부분인 P3586과는 달리 해당 메일은 원래 공개 목적이 아니었음을 감안해도 기술적인 얘기는 쏙 빼 놓고 프로파일이 "코드를 안 고치고도 안전성을 가져 갈 수 있다"는 허황된 주장에 기반해 그러니까 프로파일을 당장 집어 넣어야 한다고 주장하고 있으니 그럴 만도 하다. 스트롭스트룹이 그렇게 이름을 언급하지 않으려고 했던 러스트를 굳이 들지 않아도, 애당초 (이 또한 계속 부정하고 싶겠지만) C++의 주요 장점 중 하나였던 강력한 C 호환성이 곧 메모리 안전성의 가장 큰 적이기 때문에 프로파일이 아니라 프로파일 할아버지가 와도 안전성을 진짜로 확보하려면 코드 수정이 필수적이고, 프로파일이 그 문제를 해결한다고 주장하는 건 눈 가리고 아웅이라는 것을 이제는 충분히 많은 사람들이 깨닫지 않았는가. 스트롭스트룹이 허황된 주장을 계속 반복하는 한 C++는 안전해질 기회가 없을 듯 하다.
저는 AI에게 감사 인사를 하는 데에도 돈이 든다는 걸 깨달아버려서, 이제는 감사도 표하지 않는 삭막한 인간이 되고야 말았습니다.
@nyeongAn Nyeong (安寧) 이슈 설명할 힘도 없을때는 ai한테 '${이슈 내용} ㄱㄱ' 라고만 쳐도 열심히 잘해주는데 그럴땐 미안한 맘이 듭니다
시간이 좀 지나서 그런가, 이제 계엄자체는 그냥 또라이가 또라이짓했다 정도로 생각되는데, 그 이후 탄핵 과정에서 뭔 말같지도 않는 어거지를 부리는거 때문에 자꾸 스트레스받는다.
그동안 동료들한테 Cursor 쓰자고했는데 그들이 오소독스 Emacs 매니아들이란 문제가 있었다.
작년에 Nix로 nvidia gpu 지원까지 포함해서 구축해놓은 k3s 클러스터에다가, 오늘 아침에 1시간만에 aider로 쓸수있게 DeepSeek R1을 띄웠고 한번 써보자고 했다. 최근에 한 것 중 가장 가성비 좋은 작업인듯 하다.
타임라인과 RSS 피드에 단문 없이 게시글만 보는 필터를 추가했습니다.
@campanulaLuminα 저의 경우는 React Native라서 백엔드로 SQLite를 쓰고 있어서 괜찮습니다. 생각해보니 RxDB 등의 경우는 웹도 지원해야해서 join을 지원하는게 어려울거 같긴하네요.
JS로 짜여진, join이 되는 reactive한 로컬 DB가 필요한데요. RxDB, SignalDB는 join이 안 돼서 탈락입니다. join을 안하면 되지 않냐 할수 있는데 어떤 특이한 로직 때문에 꼭 필요합니다. 지금은 직접 sqlite 호출하는 누더기 코드로 돌아가고 있는데요.
그 코드를 리팩토링해서 제대로 된걸 만들까 말까 고민중인데, 사실 잘만들어진게 있으면 그걸 쓰고 싶습니다. 제 요구사항을 만족하는 라이브러리가 있을까요?
@dwnDWN | 社会你福哥版 님 덕분애 Hackers' Pub에 중국어 번역이 추가되었습니다!
또한, 언어 설정이 추가되어, 자신이 선호하는 복수의 언어를 선택할 수 있게 되었습니다. 이 설정은 당장은 팔로 추천에만 쓰이고 있지만, 앞으로 자동 번역이나 알고리즘 타임라인 등에 요긴하게 쓰일 예정입니다.
영어권 웹을 보다보면 autism이 한국어에서의 '자폐'보다 부정적인 늬앙스가 훨씬 덜하단 느낌을 받는다. STEM 너드들이 본인이 autistic하다고 하는 경우를 종종 보는데, 자조적인 느낌이 좀 있지만 완전 딥다크한거 같진않고, 이분법적이기보단 스펙트럼으로 보는거 같다.
@arkjunJuntai Park 사실상 저만 쓰는 소프트웨어입니다. 😂
@hongminhee洪 民憙 (Hong Minhee)
@arkjunJuntai Park 이유는 모르겠는데 개멋있네요ㄷㄷ
asbubam 님의 내가 만난 멋진 SRE
SRE 에 대한 얘기지만 멋대로(?) 개발자에 대입해서 보았습니다. 와닿는 내용을 일부 인용해 보면
여기 우리 다 처음에 그랬고 오늘도 여전히 매일 고민하고, 부딪히고, 배우면서 앞으로 나아가고 있으니까
멋진 SRE는, 도무지 답이 보이지 않는 문제를 만나도, “원래 그런거니까 흐흐” 하고 문제에 달려들어요. 내 힘으로 부족한 일은, 옆에있는 동료와 함께 반드시 해결할 수 있다고 믿어요
회사 동료들에게도 말해주고 싶은 내용들이네요. 동료들이 있으니께 걱정하지 말고 나아가라구요.
이番에 @lqezHyunwoo Park 님의 《우리의 코드를 찾아서》에 出演하여 #페디버스, #ActivityPub, #Fedify, #Hollo 等에 關해 이야기를 나눴습니다. Fedify와 Hollo의 開發 祕話 같은 게 궁금하시다면 한 番 보셔도 재밌을지도 모르겠습니다. ㅎㅎㅎ
https://snix.dev/ 저는 Rust를 못해서 기여를 못하지만 유망한 프로젝트라고 생각합니다. Rust 고수분들이 관심가져주시면 좋겠네요.
Hackers' Pub에 RSS 기능을 추가했습니다. 정확히는 RFC 4287, 일명 Atom 명세를 구현했습니다. RSS 디스커버리도 구현했기 때문에, Hackers' Pub 사용자의 프로필 페이지 링크를 RSS 앱에 추가하면 구독이 가능합니다. 확실한(?) 피드 링크를 알고 싶으시면 프로필 링크 뒤에 /feed.xml을 붙이시면 됩니다. 예를 들어, 제 피드 링크는 https://hackers.pub/@hongminhee/feed.xml입니다.
바둑에 '묘수 3번두면 바둑은 진다'라는 말이 있는데, 프로그래밍에 비슷한 말이 있을까요
어렸을 때는 Smalltalk나 Lisp 같은 언어에 마음을 많이 빼앗겼는데 (아마도 당시 쿨한 언어였던 Python이나 Ruby의 영향…) Haskell을 접한 뒤로는 언어 취향이 아주 많이 바뀐 것 같다. 일단 동적 타입 언어를… 싫어하는 정도까진 아니지만, 쓰면서 불안함을 느끼게 됐다.
Nix를 보며 알수있는건, 사람들이 메타프로그래밍을 하기 좋은 언어로 메타프로그래밍을 하는게 아니라, 런타임이 좋은 언어로 메타프로그래밍을 한다는 것이다.
Nix의 런타임이 좋다는건 일반적인 의미에서(성능이 빠르다거나) 좋다기보다는 '재현가능한 캐싱되는 빌드'라는 런타임이 아주 많은 동작을 커버하는데 Nix가 그걸 구현했다는 얘기다. 그러니까 사람들은 큰 프로그램을 쌓아올릴 대들보가 될만한 런타임이 있으면 거기서 부터 메타프로그래밍을 시작해버린다. Nix가 언어는 구리고(애초에 엄청 잘만들려고 한거같지도 않음) 메타프로그래밍을 잘하기위한 어떠한 장치도 없음에도 가장 아래에 위치할수있어서 그 역할이 맡겨져버린다.
그래서 유용한 런타임과 오브젝트 언어(또는 DSL)을 표현할 문법에 대한 좋은 아이디어가 있으면, 좀더 나은 메타프로그래밍을 하기위한 언어를 만들수 있을거라고 생각한다.
이제 게시글(긴 글)도 단문처럼 공유가 가능해졌습니다. 그리고, 타임라인에 게시글에 대한 댓글이 보이는 방식을 수정하였습니다.
사실 알고보니 이것도, 저것도 모나드였다... 하는 예시는 많은데 Category
의 예시는 뭐가 있을까? 그럼 설명이 훨씬 편해질텐데 말이다.
좀 인위적이지만 쉬운 예시를 하나 만들어보자면, 어떤 함수의 실행에 비용을 부여하는 것이다.
data Costful a b = Costful (a -> IO b) Int
f :: Costful Int String
g :: Costful String Bool
요런 정의를 생각해볼때
f . g
는 f
와 g
의 동작은 합성하고, 비용은 +
한 것이 될것이다.
instance Category where
Costful f c1 . Costful g c2 = Costful (f . g) (c1 + c2)
요렇게 말이다.
이때 f . g
의 비용은 함수를 실행하기 전에도 알수있다.
반면 그냥 f
, g
를 모나딕한 함수로 정의하고 f >=> g
이런식으로 합성했을땐, 함수를 실제로 실행하기 전에는 비용을 알수 없다. >=>
또는 >>=
의 정의를 생각해보면 쉽게 알수 있다.
Category
인스턴스는 정적인 정보를 추가로 가지고 있는 함수, 또는 함수보다 표현력이 약한데 비스무리한거(그래서 정적인 정보가 더많은) 것을 다룰때 유용하다.
Costful (f <=< g) (c1 + c2)
로 정정.
그나저나 하스켈 신택스 하이라이팅되는게 감동이군요
사실 알고보니 이것도, 저것도 모나드였다... 하는 예시는 많은데 Category
의 예시는 뭐가 있을까? 그럼 설명이 훨씬 편해질텐데 말이다.
좀 인위적이지만 쉬운 예시를 하나 만들어보자면, 어떤 함수의 실행에 비용을 부여하는 것이다.
data Costful a b = Costful (a -> IO b) Int
f :: Costful Int String
g :: Costful String Bool
요런 정의를 생각해볼때
f . g
는 f
와 g
의 동작은 합성하고, 비용은 +
한 것이 될것이다.
instance Category where
Costful f c1 . Costful g c2 = Costful (f . g) (c1 + c2)
요렇게 말이다.
이때 f . g
의 비용은 함수를 실행하기 전에도 알수있다.
반면 그냥 f
, g
를 모나딕한 함수로 정의하고 f >=> g
이런식으로 합성했을땐, 함수를 실제로 실행하기 전에는 비용을 알수 없다. >=>
또는 >>=
의 정의를 생각해보면 쉽게 알수 있다.
Category
인스턴스는 정적인 정보를 추가로 가지고 있는 함수, 또는 함수보다 표현력이 약한데 비스무리한거(그래서 정적인 정보가 더많은) 것을 다룰때 유용하다.
2022年–2023年 사이에 키우던 강아지랑 어머니, 그리고 아버지께서 次例로 떠나고 나서 憂鬱症으로 到底히 일을 할 수 없을 것 같아서 退社를 했는데, 家族의 葬禮로 因한 憂鬱과 退社로 因한 기쁨이 서로 相殺되어 제로가 된 經驗이 있다.
@hongminhee洪 民憙 (Hong Minhee) 힘내십쇼ㅠㅠ 앞으로 좋은일이 많으셨으면 좋겠네요
https://wikidocs.net/book/14314
Langchain 관련해서 한국어로 정리가 잘 정리되어 있는 듯
하스켈 패키지 검색 엔진이자 웹 서비스인 후글(Hoogle)은 서비스에 종종 문제가 생기곤 합니다. 그럴 때는 다음과 같은 대체 서비스를 이용해보세요!
한편 후글을 로컬에 설치해서 사용하는 것도 가능합니다. 잦은 서비스 문제에 질렸다면 로컬에 후글을 설치해보세요!
그리고 만약 당신이 부자라면⋯ 하스켈 재단에 기부해주세요⋯
우분투에서 뻗어나온 운영체제 이름으로 고군분투 좋은 것 같지 않아? (엉망진창 비난과 핍박을 받는다)
ActivityPub은 눈팅만 하고있었는데, 슈티에 피드를 넣기로 결정하고나니 ActivityPub를 써볼 기회가 생겼다. 따로 페디버스 서버를 팔지, 아니면 다른 방법을 쓸지(있긴 한가)를 고민해봐야한다.
모바일 뷰에서 타임라인 레이아웃이 깨지던 문제를 해결했습니다. 제보해주신 @bglbgl gwyng 님께 감사드립니다!
モバイルビューでタイムラインのレイアウトが崩れる問題を修正しました。報告してくださった @bglbgl gwyng さんに感謝します!
쉘스크립트처럼 oci 컨테이너들을 조합하는 언어가 있으면 좋겠다.
컨테이너는 샌드박싱된 파일시스템을 입력으로 받아 출력으로 쓰고, 그런 컨테이너들을 (|
pipe operator로 stdin/stdout을 잇듯이) 조합하는 것이다. 그리고 이때 각 컨테이너가 필요로하는 입력 파일/디렉토리들에 대해 일종의 타입 체크를 해서 no such file or directory
가 뜨는것을 막아줄수 있을것이다.
사실 yaml등으로 작성하는 CI/CD 설정 파일들이 비슷한 기능을 하고있는데, 이걸 좀더 멀쩡한 언어로, 로컬에서도 쓸수있으면 좋겠다.
@bglbgl gwyng 예전에 Bass라는 언어를 우연히 본 적이 있는데, 그게 떠오르네요. 말씀하신 것과는 좀 다르지만요.
@bglbgl gwyng 예전에 Bass라는 언어를 우연히 본 적이 있는데, 그게 떠오르네요. 말씀하신 것과는 좀 다르지만요.
@hongminhee洪 民憙 (Hong Minhee) 오 제가 원하는 방향인거 같은데요? 감사합니다
쉘스크립트처럼 oci 컨테이너들을 조합하는 언어가 있으면 좋겠다.
컨테이너는 샌드박싱된 파일시스템을 입력으로 받아 출력으로 쓰고, 그런 컨테이너들을 (|
pipe operator로 stdin/stdout을 잇듯이) 조합하는 것이다. 그리고 이때 각 컨테이너가 필요로하는 입력 파일/디렉토리들에 대해 일종의 타입 체크를 해서 no such file or directory
가 뜨는것을 막아줄수 있을것이다.
사실 yaml등으로 작성하는 CI/CD 설정 파일들이 비슷한 기능을 하고있는데, 이걸 좀더 멀쩡한 언어로, 로컬에서도 쓸수있으면 좋겠다.