SlideShare a Scribd company logo
1 of 43
Download to read offline
무민(조현석) @ 컨스택츠
(내가 감동 먹은)
Haskell에서 Postgresql을
사용하는 우아한 방법
Quasiquotation
옛날 옛날 아주 먼 옛날에
컨스택츠에 메인 디비가 MongoDB였어요
단테
“postgresql로 이사갑시다!”
나머지 코드(DB, Kafka)
컨스택츠 BE 구성
도메인
Types Service
김은민(토드). [Dev Dive 2022]. (2022. 11. 16.). [Dev Dive_ Backend Day] 하스켈로 백엔드 시스템 만든 이야기 [영상]. 유튜브. https://www.youtube.com/watch?v=YBLZGUeNSu4
SQL이 문자열로?
혹시 쿼리 매퍼일까?
ORM, ODM, FRM은?
이것은 문자열이 아닙니다(?)
QuasiQuotes
쿼리 매퍼도 아닙니다
빨라진 개발 리듬
기능 코딩 -> 기능 해 봄 -> 안 됨 -> 코딩 -> 해 봄 -> 안 됨 ... -> 완성
기능 코딩 -> 테스트 실행 -> 실패 -> 코딩 -> 테스트 실행 -> ... -> 완성
기능 코딩 -> 컴파일 -> 에러 -> 코딩 -> 컴파일 -> 에러 ... -> 완성
사실은 거의 코딩 시점
김은민. [Dev Dive 2022]. (2022. 11. 16.). [Dev Dive_ Backend Day] 하스켈로 백엔드 시스템 만든 이야기 [영상]. 유튜브. https://www.youtube.com/watch?v=YBLZGUeNSu4
애초에 우리는
왜
ORM이라는 걸 쓰게 되었을까?
혹시 내가 함수뽕에 빠져서 시야가 흐려진게 아닐까?
“SQL 중심적인 개발의 문제점”
“누구나 그럴싸한 계획을 갖고 있다.
Hello World를 벗어나기 전까지는”
Why It’s Nice to be Quoted
Quasiquoting for Haskell
개발자는 다양한 DSL을 사용합니다.
JSON
정규표현식
XML
YAML
언어/언어확장이 지원
JSX
정규표현식
언어의 문법에 맞게 내부에서 사용
Kotlin DSL
Querydsl
외부 파일을 사용한다.
Quasiquotation
(파서를 작성하는 것보다 약간의 작업이 더 필요하지만)
Quasiquoting으로 묶인 모든 데이터의 타입이 정확하
다는 것을 컴파일 시간 보장
[quoter| string |]
• ⟨quoter⟩는 임포트된 quoter의 이름이어야 합니다. 임의의 표현이 될 수 없습니다.
• ⟨quoter⟩는 "e", "t", "d" 또는 "p"일 수 없습니다. 템플릿 하스켈 quotations과 겹치기
때문입니다.
• 토큰 [quoter|에는 공백이 없어야 합니다.
• quote된 ⟨string⟩은 임의적일 수 있으며 개행을 포함할 수 있습니다.
• 따옴표로 묶인 ⟨string⟩은 첫 번째 "|]"에서 끝납니다. 그 외 절대 끝나지 않습니다. 해당 문
자 시퀀스를 문자열에 포함하려면 고유한 이스케이프 규칙(예: 대신 문자열 "|~]" 사용)을
만들고 quoter 함수가 "|~]"를 "| ]”로 변환해야 한다.
Quasiquote는 다음 위치 중 하나에서 등장 할 수 있다.
• 표현식
• 패턴
• 타입
• 최상위 선언
data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp,
quotePat :: String -> Q Pat,
quoteType :: String -> Q Type,
quoteDec :: String -> Q [Dec]
}
그렇다면 내부를 들여다 보자
https://github.com/dylex/postgresql-typed/blob/master/Database/PostgreSQL/Typed/Query.hs
그럼요!
나도 QuasiQuoter를 만들 수 있을까?
-- >>> eval [expr|1|]
-- 1
-- >>> eval [expr|1 + 2|]
-- 3
-- >>> eval [expr|1+2+3|]
-- 6
data Expr = IntExpr Integer
| BinopExpr BinOp Expr Expr
deriving(Show, Typeable, Data)
data BinOp = AddOp
| SubOp
| MulOp
| DivOp
deriving(Show, Typeable, Data)
data Expr = IntExpr Integer
| AntiIntExpr String
| BinopExpr BinOp Expr Expr
| AntiExpr String
deriving(Show, Typeable, Data)
x :: Integer
x = 1
eval [expr|$x + 3|]
parseExpr :: m => String -> m Expr
parseExpr s = …
expr :: QuasiQuoter
expr = QuasiQuoter { quoteExp = quoteExprExp,
quotePat = quoteExprPat,
quoteType = error "",
quoteDec = error "" }
quoteExprExp :: String -> TH.ExpQ
quoteExprExp s = do
expr <- parseExpr s
liftData expr
quoteExprExp :: String -> TH.ExpQ
quoteExprExp s = do loc <- TH.location
let pos = (TH.loc_filename loc,
fst (TH.loc_start loc),
snd (TH.loc_start loc))
expr <- parseExpr pos s
dataToExpQ (const Nothing `extQ` antiExprExp) expr
antiExprExp :: Expr -> Maybe (TH.Q TH.Exp)
antiExprExp (AntiIntExpr v) = Just $ TH.appE (TH.conE (TH.mkName "IntExpr"))
(TH.varE (TH.mkName v))
antiExprExp (AntiExpr v) = Just $ TH.varE (TH.mkName v)
antiExprExp _ = Nothing
quoteExprPat :: String -> TH.PatQ
quoteExprPat s = do loc <- TH.location
let pos = (TH.loc_filename loc,
fst (TH.loc_start loc),
snd (TH.loc_start loc))
expr <- parseExpr pos s
dataToPatQ (const Nothing `extQ` antiExprPat) expr
antiExprPat :: Expr -> Maybe (TH.Q TH.Pat)
antiExprPat (AntiIntExpr v) = Just $ TH.conP (TH.mkName "IntExpr")
[TH.varP (TH.mkName v)]
antiExprPat (AntiExpr v) = Just $ TH.varP (TH.mkName v)
antiExprPat _ = Nothing
eval :: Expr -> Integer
eval (IntExpr n) = n
eval (BinopExpr op x y) = (opToFun op) (eval x) (eval y)
where
opToFun AddOp = (+)
opToFun SubOp = (-)
opToFun MulOp = (*)
opToFun DivOp = div
eval' :: Expr -> Integer
eval' [expr|$int:x|] = x
eval' [expr|$x + $y|] = eval' x + eval' y
eval' [expr|$x - $y|] = eval' x - eval' y
eval' [expr|$x * $y|] = eval' x * eval' y
eval' [expr|$x / $y|] = eval' x `div` eval' y
결론
• 하스켈에는 DSL을 임베드 시킬 수 있는 QuasiQuotes라는 것이 있다.
• (그걸로 만들어진 라이브러리를) 써보니 편하더라

More Related Content

What's hot

Ndc14 분산 서버 구축의 ABC
Ndc14 분산 서버 구축의 ABCNdc14 분산 서버 구축의 ABC
Ndc14 분산 서버 구축의 ABCHo Gyu Lee
 
LISA2019 Linux Systems Performance
LISA2019 Linux Systems PerformanceLISA2019 Linux Systems Performance
LISA2019 Linux Systems PerformanceBrendan Gregg
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기Sang Heon Lee
 
Git을 조금 더 알아보자!
Git을 조금 더 알아보자!Git을 조금 더 알아보자!
Git을 조금 더 알아보자!Young Kim
 
Performance Wins with eBPF: Getting Started (2021)
Performance Wins with eBPF: Getting Started (2021)Performance Wins with eBPF: Getting Started (2021)
Performance Wins with eBPF: Getting Started (2021)Brendan Gregg
 
Kernel Recipes 2017 - Understanding the Linux kernel via ftrace - Steven Rostedt
Kernel Recipes 2017 - Understanding the Linux kernel via ftrace - Steven RostedtKernel Recipes 2017 - Understanding the Linux kernel via ftrace - Steven Rostedt
Kernel Recipes 2017 - Understanding the Linux kernel via ftrace - Steven RostedtAnne Nicolas
 
iptables 101- bottom-up
iptables 101- bottom-upiptables 101- bottom-up
iptables 101- bottom-upHungWei Chiu
 
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018Kenneth Ceyer
 
Kernel Recipes 2019 - ftrace: Where modifying a running kernel all started
Kernel Recipes 2019 - ftrace: Where modifying a running kernel all startedKernel Recipes 2019 - ftrace: Where modifying a running kernel all started
Kernel Recipes 2019 - ftrace: Where modifying a running kernel all startedAnne Nicolas
 
Phpをいじり倒す10の方法
Phpをいじり倒す10の方法Phpをいじり倒す10の方法
Phpをいじり倒す10の方法Moriyoshi Koizumi
 
초보자를 위한 분산 캐시 이야기
초보자를 위한 분산 캐시 이야기초보자를 위한 분산 캐시 이야기
초보자를 위한 분산 캐시 이야기OnGameServer
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심흥배 최
 
[오픈소스컨설팅]Scouter 설치 및 사용가이드(JBoss)
[오픈소스컨설팅]Scouter 설치 및 사용가이드(JBoss)[오픈소스컨설팅]Scouter 설치 및 사용가이드(JBoss)
[오픈소스컨설팅]Scouter 설치 및 사용가이드(JBoss)Ji-Woong Choi
 
Linux Profiling at Netflix
Linux Profiling at NetflixLinux Profiling at Netflix
Linux Profiling at NetflixBrendan Gregg
 
Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표Kwen Won Lee
 

What's hot (20)

Ndc14 분산 서버 구축의 ABC
Ndc14 분산 서버 구축의 ABCNdc14 분산 서버 구축의 ABC
Ndc14 분산 서버 구축의 ABC
 
LISA2019 Linux Systems Performance
LISA2019 Linux Systems PerformanceLISA2019 Linux Systems Performance
LISA2019 Linux Systems Performance
 
Introduction to Data Oriented Design
Introduction to Data Oriented DesignIntroduction to Data Oriented Design
Introduction to Data Oriented Design
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기
 
Git을 조금 더 알아보자!
Git을 조금 더 알아보자!Git을 조금 더 알아보자!
Git을 조금 더 알아보자!
 
Performance Wins with eBPF: Getting Started (2021)
Performance Wins with eBPF: Getting Started (2021)Performance Wins with eBPF: Getting Started (2021)
Performance Wins with eBPF: Getting Started (2021)
 
Kernel Recipes 2017 - Understanding the Linux kernel via ftrace - Steven Rostedt
Kernel Recipes 2017 - Understanding the Linux kernel via ftrace - Steven RostedtKernel Recipes 2017 - Understanding the Linux kernel via ftrace - Steven Rostedt
Kernel Recipes 2017 - Understanding the Linux kernel via ftrace - Steven Rostedt
 
iptables 101- bottom-up
iptables 101- bottom-upiptables 101- bottom-up
iptables 101- bottom-up
 
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
 
Kernel Recipes 2019 - ftrace: Where modifying a running kernel all started
Kernel Recipes 2019 - ftrace: Where modifying a running kernel all startedKernel Recipes 2019 - ftrace: Where modifying a running kernel all started
Kernel Recipes 2019 - ftrace: Where modifying a running kernel all started
 
eBPF Basics
eBPF BasicseBPF Basics
eBPF Basics
 
eBPF maps 101
eBPF maps 101eBPF maps 101
eBPF maps 101
 
eBPF/XDP
eBPF/XDP eBPF/XDP
eBPF/XDP
 
Phpをいじり倒す10の方法
Phpをいじり倒す10の方法Phpをいじり倒す10の方法
Phpをいじり倒す10の方法
 
초보자를 위한 분산 캐시 이야기
초보자를 위한 분산 캐시 이야기초보자를 위한 분산 캐시 이야기
초보자를 위한 분산 캐시 이야기
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심
 
[오픈소스컨설팅]Scouter 설치 및 사용가이드(JBoss)
[오픈소스컨설팅]Scouter 설치 및 사용가이드(JBoss)[오픈소스컨설팅]Scouter 설치 및 사용가이드(JBoss)
[오픈소스컨설팅]Scouter 설치 및 사용가이드(JBoss)
 
Linux Profiling at Netflix
Linux Profiling at NetflixLinux Profiling at Netflix
Linux Profiling at Netflix
 
Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표
 
DPDK KNI interface
DPDK KNI interfaceDPDK KNI interface
DPDK KNI interface
 

Similar to liftIO 2022 quasiquote

Programming skills 1부
Programming skills 1부Programming skills 1부
Programming skills 1부JiHyung Lee
 
Node js[stg]onimusha 20140822
Node js[stg]onimusha 20140822Node js[stg]onimusha 20140822
Node js[stg]onimusha 20140822병헌 정
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기Yongha Yoo
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 명신 김
 
NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현noerror
 
Java advancd ed10
Java advancd ed10Java advancd ed10
Java advancd ed10hungrok
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기Seong Won Mun
 
자바와 사용하기2
자바와 사용하기2자바와 사용하기2
자바와 사용하기2destinycs
 
Python programming for Bioinformatics
Python programming for BioinformaticsPython programming for Bioinformatics
Python programming for BioinformaticsHyungyong Kim
 
20150212 c++11 features used in crow
20150212 c++11 features used in crow20150212 c++11 features used in crow
20150212 c++11 features used in crowJaeseung Ha
 
android_thread
android_threadandroid_thread
android_threadhandfoot
 
Functional thinking - 책 리뷰 1탄
Functional thinking - 책 리뷰 1탄Functional thinking - 책 리뷰 1탄
Functional thinking - 책 리뷰 1탄Jeong-gyu Kim
 
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로Oracle Korea
 
[Swift] Protocol (2/2)
[Swift] Protocol (2/2)[Swift] Protocol (2/2)
[Swift] Protocol (2/2)Bill Kim
 
0327.web&ruby&rails
0327.web&ruby&rails0327.web&ruby&rails
0327.web&ruby&rails민정 김
 
Scala, Scalability
Scala, ScalabilityScala, Scalability
Scala, ScalabilityDongwook Lee
 

Similar to liftIO 2022 quasiquote (20)

Programming skills 1부
Programming skills 1부Programming skills 1부
Programming skills 1부
 
Node js[stg]onimusha 20140822
Node js[stg]onimusha 20140822Node js[stg]onimusha 20140822
Node js[stg]onimusha 20140822
 
ES6 for Node.js Study 2주차
ES6 for Node.js Study 2주차ES6 for Node.js Study 2주차
ES6 for Node.js Study 2주차
 
Scala
ScalaScala
Scala
 
Regex
RegexRegex
Regex
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
 
NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현
 
Java advancd ed10
Java advancd ed10Java advancd ed10
Java advancd ed10
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기
 
자바와 사용하기2
자바와 사용하기2자바와 사용하기2
자바와 사용하기2
 
Python programming for Bioinformatics
Python programming for BioinformaticsPython programming for Bioinformatics
Python programming for Bioinformatics
 
20150212 c++11 features used in crow
20150212 c++11 features used in crow20150212 c++11 features used in crow
20150212 c++11 features used in crow
 
android_thread
android_threadandroid_thread
android_thread
 
Functional thinking - 책 리뷰 1탄
Functional thinking - 책 리뷰 1탄Functional thinking - 책 리뷰 1탄
Functional thinking - 책 리뷰 1탄
 
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
 
Java.next
Java.nextJava.next
Java.next
 
[Swift] Protocol (2/2)
[Swift] Protocol (2/2)[Swift] Protocol (2/2)
[Swift] Protocol (2/2)
 
0327.web&ruby&rails
0327.web&ruby&rails0327.web&ruby&rails
0327.web&ruby&rails
 
Scala, Scalability
Scala, ScalabilityScala, Scalability
Scala, Scalability
 

liftIO 2022 quasiquote