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

송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010
devCAT Studio, NEXON
 
게임 프레임워크의 아키텍쳐와 디자인 패턴
게임 프레임워크의 아키텍쳐와 디자인 패턴게임 프레임워크의 아키텍쳐와 디자인 패턴
게임 프레임워크의 아키텍쳐와 디자인 패턴
MinGeun Park
 
[0903 구경원] recast 네비메쉬
[0903 구경원] recast 네비메쉬[0903 구경원] recast 네비메쉬
[0903 구경원] recast 네비메쉬
KyeongWon Koo
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템
QooJuice
 
Ndc2012 최지호 텍스쳐 압축 기법 소개
Ndc2012 최지호 텍스쳐 압축 기법 소개Ndc2012 최지호 텍스쳐 압축 기법 소개
Ndc2012 최지호 텍스쳐 압축 기법 소개
Jiho Choi
 
R2서버정진욱
R2서버정진욱R2서버정진욱
R2서버정진욱
jungjinwouk
 

What's hot (20)

송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010
 
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기
 
C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현
 
Multiplayer Game Sync Techniques through CAP theorem
Multiplayer Game Sync Techniques through CAP theoremMultiplayer Game Sync Techniques through CAP theorem
Multiplayer Game Sync Techniques through CAP theorem
 
AAA게임_UI_최적화_및_빌드하기.pptx
AAA게임_UI_최적화_및_빌드하기.pptxAAA게임_UI_최적화_및_빌드하기.pptx
AAA게임_UI_최적화_및_빌드하기.pptx
 
Umg ,이벤트 바인딩, Invaidation Box
Umg ,이벤트 바인딩, Invaidation BoxUmg ,이벤트 바인딩, Invaidation Box
Umg ,이벤트 바인딩, Invaidation Box
 
청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기
 
[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지
[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지
[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지
 
게임 프레임워크의 아키텍쳐와 디자인 패턴
게임 프레임워크의 아키텍쳐와 디자인 패턴게임 프레임워크의 아키텍쳐와 디자인 패턴
게임 프레임워크의 아키텍쳐와 디자인 패턴
 
[0903 구경원] recast 네비메쉬
[0903 구경원] recast 네비메쉬[0903 구경원] recast 네비메쉬
[0903 구경원] recast 네비메쉬
 
나만의 엔진 개발하기
나만의 엔진 개발하기나만의 엔진 개발하기
나만의 엔진 개발하기
 
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
 
基礎からのCode Contracts
基礎からのCode Contracts基礎からのCode Contracts
基礎からのCode Contracts
 
Ue4 에서의 환경변화 구현
Ue4 에서의 환경변화 구현Ue4 에서의 환경변화 구현
Ue4 에서의 환경변화 구현
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템
 
Mvpvm pattern
Mvpvm patternMvpvm pattern
Mvpvm pattern
 
Ndc2012 최지호 텍스쳐 압축 기법 소개
Ndc2012 최지호 텍스쳐 압축 기법 소개Ndc2012 최지호 텍스쳐 압축 기법 소개
Ndc2012 최지호 텍스쳐 압축 기법 소개
 
R2서버정진욱
R2서버정진욱R2서버정진욱
R2서버정진욱
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座
 

Similar to liftIO 2022 quasiquote

Node js[stg]onimusha 20140822
Node js[stg]onimusha 20140822Node js[stg]onimusha 20140822
Node js[stg]onimusha 20140822
병헌 정
 
자바와 사용하기2
자바와 사용하기2자바와 사용하기2
자바와 사용하기2
destinycs
 

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
 
Scalability
ScalabilityScalability
Scalability
 

liftIO 2022 quasiquote