class: center, middle # Shapeless를 이용한
제네릭 프로그래밍 박지수 (CTO, 두물머리) --- ## 실제 사례 날짜들만 일주일씩 미룰 수 없을까? ``` val els1 = Els( common = Common( // ... settlementDate = `LocalDate`.of(2016, 2, 17), finalValuationDate = `LocalDate`.of(2019, 2, 12), issueDate = `LocalDate`.of(2016, 2, 18), maturityDate = `LocalDate`.of(2019, 2, 15)`), placement = Placement( // ... offeringPeriod = DateTimePeriod( `LocalDateTime`.of(2016, 2, 16, 9, 0), `LocalDateTime`.of(2016, 2, 17, 13, 0))), // ... earlyRedemption = List( EarlyRedemption(`LocalDate`.of(2016, 8, 11), /* ... */), EarlyRedemption(`LocalDate`.of(2017, 2, 14), /* ... */), // ... ``` --- ## 안 될 거야 없지만 ### 매크로 - 강력하지만 - 잘 만들기 어려워요 - (아직은) 컴파일러를 어느 정도 알아야 (Tree, Ident, Apply...) - 현재진행형 - scala.reflect - scala.meta - scala.macros - [SCP-014](https://github.com/scalacenter/macros) -- ### 런타임 리플렉션 -- - 네??????? --- ## Shapeless ### 스칼라 제네릭 프로그래밍 라이브러리 - https://github.com/milessabin/shapeless - [Scrap your boilerplate](https://www.microsoft.com/en-us/research/publication/scrap-your-boilerplate-with-class/) - [Higher rank polymorphism](http://camlunity.ru/swap/ocaml/Sexy%20Types.pdf) ### 제네릭 프로그래밍? - [CoRecursive: 008 - Generic Programming with Miles Sabin](https://corecursive.com/008-generic-programming-with-miles-sabin) > "The kind of polymophism your language does not support **yet**" --- ## 실제 코드 ``` import shapeless.{everywhere, Poly1} class shiftDate(days: Int) extends `Poly1` { implicit val dateDate = at[Date](_.plusDays(days)) implicit val dateDateTime = at[DateTime](_.plusDays(days)) } object shift5 extends shiftDate(5) val els2 = `everywhere`(shift5)(els1) ``` -- ### 끝 --- ## 어디에 쓰나요 - [Akka-http](https://github.com/akka/akka-http) (구 spray): The Streaming-first HTTP server/module of Akka - [Breeze](https://github.com/scalanlp/breeze): A numerical processing library for Scala - [Circe](https://circe.github.io/circe/): A JSON library for Scala powered by Cats - [Doobie](https://tpolecat.github.io/doobie/): A principled JDBC layer for Scala - [Finch](https://finagle.github.io/finch/): Scala combinator library for building Finagle HTTP services - [Frameless](https://github.com/typelevel/frameless): Expressive types for Spark - [Kittens](https://github.com/milessabin/kittens): Automatic type class derivation for Cats - [Monocle](http://julien-truffaut.github.io/Monocle/): Optics library for Scala - [Pureconfig](https://pureconfig.github.io/): A boilerplate-free library for loading configuration files - [Refined](https://github.com/fthomas/refined): Simple refinement types for Scala - [Scodec](http://scodec.org/): Scala combinator library for working with binary data - 등등 https://github.com/milessabin/shapeless/wiki/Built-with-shapeless --- ## Implicit resolution - Lexical scope - Companion object - Chaining --- ## Path-dependent type - `shapeless.{Nat, HList, Coproduct, ...}` --- ## Value-dependent type - `shapeless.Witness` - [SIP-23](https://docs.scala-lang.org/sips/42.type.html) - `-Yliteral-types` in Scala 2.13 --- ## Isomorphism - `shapeless.Generic` - Product - Coproduct --- ## `Aux` pattern - http://gigiigig.github.io/posts/2015/09/13/aux-pattern.html --- class: center, middle # 코드를 봅시다 --- ## 좋기만 한가요 -- ### 그럴리가요 - 컴파일 시간 증가 - (상대적으로) 난해한 코드 - ADT <-> `HList`/`Coproduct` 변환으로 인한 런타임 오버헤드 - 컴파일러 버그를 밟을 때가 있음 -- ### 일부 대안 - [Magnolia](https://magnolia.work/): fast and unintrusive typeclass derivation - [scalaz-deriving](https://gitlab.com/fommil/scalaz-deriving): deriving for scala data types - 그 외 각종 매크로 라이브러리 -- - `Ctrl+C`, `Ctrl+V` --- ## 언제 ### 안 쓰는 게 나은가요 - 코드 중복이 거슬리지만 잘 모아놔서 한꺼번에 고치기 어렵지 않을 때 - 런타임 성능이 많이 중요할 때 ### 쓰면 좋은가요 - 아주 복잡한 ADT를 다뤄야 할 때 - 타입 선언을 해봤자 런타임에 자꾸 깨질 때 (직렬화 등) - 지금 붙여넣는 비슷한 코드 더미를 도저히 유지보수할 자신이 없을 때 --- ## 스칼라 개발자를 모십니다 -- ## 데이터/인프라 엔지니어도 모십니다 -- ## 웹 프론트엔드 전문가도요 -- ### https://github.com/doomoolmori/colleagues -- ##
recruit@doomoolmori.com
--- class: center, middle #
recruit@doomoolmori.com
--- class: center, middle # 감사합니다. ##
recruit@doomoolmori.com