Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Haskell/Servantで行う安全かつ高速なAPI開発

 Haskell/Servantで行う安全かつ高速なAPI開発

Haskellを業務に導入し、ガッツリ使っている経験をもとに、技術スタックや開発スタイルを共有しつつ、Haskellのメリットや「何ができるのか?」を話します。
また、ライブラリの充実度も共有します。

お問い合わせはこちらのtwitterアカウントへ: @nakaji_dayo

B60e45c2f2adbfef9aa2d7c200b27f67?s=128

Daishi Nakajima

November 10, 2018
Tweet

Transcript

  1. )BTLFMM4FSWBOUͰߦ͏ ҆શ͔ͭߴ଎ͳ"1*։ൃ גࣜձࣾ-&.0$50தౢେ࢚ )BTLFMM%BZ )BTLFMMͪΐͬͱڵຯ͋Δਓ

  2. ΞδΣϯμ  )BTLFMMͷ༻్  ٕज़ελοΫ  ࣮ࡍͷ࢖͍ํɾ։ൃελΠϧ  ར༻ϥΠϒϥϦͷ֓ཁ

  3. ໨ඪ w )BTLFMMΛ ۀ຿Ͱ ࢖ͬͯΈΑ͏ʂ w ࢖͏͜ͱΛݕ౼͠Α͏ʂ ͱ͍͏ؾ࣋ͪʹͳ͍͚ͬͯͨͩΔΑ͏ؤுΓ·͢

  4. )BTLFMMͷ༻్

  5. )BTLFMMͷ༻్ w #BDLFOE 8FC"1*#BUDI ͷ։ൃ w Ұൠతͳ8&#ϞόΠϧΞϓϦ w ௚ۙ w

    ՝ۚͷ͋Δ4/4ʢ#&ਓ݄ఔ౓ʣ
  6. ٕज़ελοΫ

  7. ར༻ٕज़  -BOH)BTLFMM  8"'4FSWBOU  2VFSZ#VJMEFS 3.)BTLFMM3FMBUJPOBM3FDPSE

  8. )BTLFMMͷ঺հ w ७ਮؔ਺ܕϓϩάϥϛϯάݴޠ w ෭࡞༻ͷ෼཭ w ੩తܕ෇͚ܕਪ࿦ w ஗ԆධՁ

  9. 4FSWBOUͷ঺հ w ബ͍8FC"QQMJDBUJPO'SBNFXPSL w Ұൠతͳ8"' w ػೳ͸γϯϓϧ w OPEFFYQSFTT SVCZTJOBUSB

  10. 4FSWBOUͷಛ௃ w ܕϨϕϧϓϩάϥϛϯά w "1*Λ)BTLFMMͷܕͱͯ͠ఆٛ w ܕ҆શͳ8FC"QQMJDBUJPOͷ։ൃ w ܕ͔Β෭࢈෺ͷੜ੒

  11. )BTLFMM3FMBUJPOBM3FDPSE w ந৅తͰܕ҆શͰ߹੒ՄೳͳΫΤϦδΣωϨʔλʔ w %#ͷεΩʔϚ͔ΒɺίϯύΠϧ࣌ʹܕΛੜ੒ w ͜ͷܕΛ࢖͍ΫΤϦΛهड़ɺίϯύΠϧ͕௨Ε͹ਖ਼͍͠ 42- w ໰͍߹Θͤ݁Ռ΋ܕʹϚοϐϯά

  12. ࣮ࡍͷ࢖͍ํɾ։ൃελΠϧ

  13. 4FSWBOU "1*ͷܕ શମ͕ܕͰܨ͕ͬͨঢ়ଶ 3FRVFTU %# )33 )BOEMFS 4FSWJDF 7JFX 3FTQPOTF

    &OUJUZ )551 2VFSZ ܕͷ֎ͷੈք ܕͷ֎ͷੈք Y ઃܭ্ͷ੍໿ υΩϡϝϯτ౳ͷੜ੒
  14. ࣮ྫ  "1*ͷઃܭɾܕఆٛ  4XBHHFS .PDL4FSWFS౳ͷੜ੒  '8ͷ֦ு  ࣮૷ɺςετ

  15. "1*ΛܕͰఆٛ w ϢʔβʔҰཡͷऔಘ DVSM9(&5VTFST QBHF  w Ϣʔβʔ৘ใͷߋ৽ DVSM91"5$)VTFSTE\OBNFGPP^ type

    API = "users" :> QueryParam "page" Int :> Get '[JSON] GetUsersResponse :<|> "users" :> Capture "id" Int :> ReqBody '[JSON] PostUsersBody :> Patch '[JSON] Int type MyMap = Map Int String
  16. "1*ΛܕͰఆٛ w ϢʔβʔҰཡͷऔಘ DVSM9(&5VTFST QBHF  w Ϣʔβʔ৘ใͷߋ৽ DVSM91"5$)VTFSTE\OBNFGPP^ type

    API = "users" :> QueryParam "page" Int :> Get '[JSON] GetUsersResponse :<|> "users" :> Capture "id" Int :> ReqBody '[JSON] PostUsersBody :> Patch '[JSON] Int type MyMap = Map Int String 1BUI4FHNFOU΍1BSBNFUFS౳ ΤϯυϙΠϯτͷߏ੒Λͭͳ͙ ΤϯυϙΠϯτಉ࢜Λͭͳ͙ ୯७ͳUZQFBMJBT
  17. ରԠ͢Δ࣮૷ getUsers :: Maybe Int -> Handler GetUsersResponse getUsers mpage

    = undefined patchUser :: Int -> PatchUsersBody -> Handler Int patchUser userId body = undefined api :: Server API api = getUsers :<|> putUsers aఆٛͱ࣮૷ͷҰக͕อূ͞Ε͍ͯΔ
  18. )BOEMFSʹ͍ͭͯ w ෭࡞༻ͷ͋Δܭࢉ w #BE3FRVFTU౳ͷྫ֎ΛUISPX Handler runHandler' :: ExceptT ServantErr

    IO a f :: Handler String f = do rs <- liftIO $ httpRequest "who am i" when (rs == YouAreTeapot) $ throwError err418 return $ “my name is " ++ rs
  19. ࣮ࡍʹ"1*Λఆٛ͢Δ data HogeRequest = HogeRequest { _id :: Int64 ,

    _name :: String } type API = "hoge" :> ReqBody '[JSON] HogeRequest … api = undefined 3FRVFTU#PEZ΍3FTQPOTFͷܕ΋ఆٛ ΤϯυϙΠϯτΛఆٛ ͍͔ͭ͘ͷܕΫϥεͷΠϯελϯεʹ͓ͯ͘͠ UP+40/ GSPN+40/ %FGBVMU 5P4DIFNB "SCJUSBSZ FUD
  20. ܕΫϥε w 5P+40/'SPN+40/+40/ʹม׵Մೳ w %FGBVMUσϑΥϧτͷ஋Λੜ੒Մೳ w 5P4DIFNB4XBHHFSυΩϡϝϯτʹม׵Մೳ w "SCJUSBSZϥϯμϜͳ஋Λੜ੒Մೳ w

    -FOTHFUUFSTFUUFS
  21. ࣮ྫ  "1*ͷઃܭɾܕఆٛ  4XBHHFS .PDL4FSWFS౳ͷੜ੒  '8ͷ֦ு  ࣮૷ɺςετ

  22. TXBHHFS NPDL౳ͷੜ੒ w "1*ఆ͔ٛΒੜ੒ w 4XBHHFS w TFSWBOUTXBHFS w ࣮૷ͱυΩϡϝϯτ͕ͣΕͳ͍ݴޠͷྗΛ࢖͑Δ

    w ϞοΫαʔόʔ w TFSWBOUNPDL w "SCJUSBSZ 2VJDL$IFDL
  23. ࣮ྫ  "1*ͷઃܭɾܕఆٛ  4XBHHFS .PDL4FSWFS౳ͷੜ੒  '8ͷ֦ு  ࣮૷ɺςετ

  24. )BOEMFSͷ֦ு w )BOEMFSʹඞཁͳϞφυΛ߹੒͢Δ newtype AppM a = AppM { runAppM

    :: ReaderT Context Handler a } deriving (...) 3FBEFS άϩʔόϧʹࢀর͢Δ஋Λѻ͏  ઃఆ஋ɺ$POOFDUJPO1PPM 5SBOTBDUJPO؅ཧ ౳ 3FBEFSΛ߹੒
  25. ܕͰઃܭ্ͷ੍໿Λߦ͏ w DMBTT  .POBE4FSWJDFN w ෭࡞༻࣮ߦՄೳ %#΁ͷΞΫηεՄೳ )551తͳྫ֎ ౤͛ͨΓ͸Ͱ͖ͳ͍

    w DMBTT ʜ .POBE7JFXN w ઃఆ஋ͷࢀর͸Մೳ ෭࡞༻ى͜͞ͳ͍
  26. ܕͰઃܭ্ͷ੍໿Λߦ͏ queryM :: MonadService m => a -> m b

    … renderUser :: MonadView m => User -> m UserView renderUser x = do imgs <- queryM UserImages x … ίϯύΠϧΤϥʔ
  27. ࣮ྫ  "1*ͷઃܭɾܕఆٛ  4XBHHFS .PDL4FSWFS౳ͷੜ੒  '8ͷ֦ு  ࣮૷ɺςετ

  28. 4FSWJDFͷ࣮૷ w ϩδοΫॻ͘

  29. 7JFXͷ࣮૷ w "1*ͳͷͰ+40/ʹͰ͖Δσʔλܕʹ஋ΛೖΕΔ࡞ۀ w ҼΈʹɺ)5.-౳Λѻ͏৔߹ɺςϯϓϨʔτΤϯδϯ͕ ͋Δ w IFUFSPDFQIBMVT΍TIBLFTQFBSFͳͲܕ҆શͳςϯ ϓϨʔτ͕͓͢͢Ί &NBJMͳͲʹར༻

  30. 3&1-ͰԥΔ > runAppM’ $ postMessagesR $ def & text .~

    “hello” Right (Message {_id = 123, _userName = “hoge”, image=… postMessagesR :: PostMessageBody -> AppM Message ࣍ͷ)BOEMFSʢΤϯυϙΠϯτʣΛςετ͍ͨ͠ HIDJͰ؆୯ʹ࣮ߦ
  31. 4FSWBOU "1*ͷܕ શମ͕ܕͰܨ͕ͬͨঢ়ଶ 3FRVFTU %# )33 )BOEMFS 4FSWJDF 7JFX 3FTQPOTF

    &OUJUZ )551 2VFSZ ܕͷ֎ͷੈք ܕͷ֎ͷੈք Y ઃܭ্ͷ੍໿ υΩϡϝϯτ౳ͷੜ੒
  32. શମ͕ܕͰܨ͕ͬͨঢ়ଶ w ୯७ͳόάΛ๷͙ɻ w ࣗ໌ͳςετΛॻ͘ඞཁ͕ͳ͍ɻ w ϩδοΫʹूத w ྫ͸3%# )33͕ͩɺ)BTLFMMͰ͸Ϩϕϧͷࠩ͸͋ΕͲɺ

    ຆͲͷϥΠϒϥϦ͕ܕ҆શͰ͋Δ܏޲͕͋Δɻ
  33. ར༻ϥΠϒϥϦͷ ֓ཁ

  34. ଞɺར༻͍ͯ͠ΔϥΠϒϥϦ TFSWBOUTFSWFS TFSWBOUBVUITFSWFS TFSWBOUNPDL TFSWBOUNVMUJQBSU TFSWBOUTXBHHFS IUUQUZQFT JNBHFUZQF XBJ XBJDPST

    XBSQ 8FC BFTPO EBUBEFGBVMUDMBTT MFOT VVJE ZBNM UZQFMFWFMTFUT VOPSEFSFEDPOUBJOFST DBTTBWB WFDUPS QEGUPPMCPYEPDVNFOU VOJDPEFTIPX NJNFNBJM DPOUBJOFST σʔλ KPTF ҉߸ )%#$QPTUHSFTRM )%#$TFTTJPO SFMBUJPOBMRVFSZ SFTPVSDFQPPM TRMXPSET 3%# HPHPM HPHPMDPSF pSFCBTFBENJO BNB[POLB BNB[POLBDPSF BNB[POLBT BNB[POLBTFT IUUQDMJFOU IUUQDPOEVJU DPOOFDUJPO TTJHOFS CMPPEIPVOE ଞΫϥΠΞϯτ IFUFSPDFQIBMVT CMB[FNBSLVQ ςϯϓϨʔτ LBUJQ NPOBEMPHHFS ϩΨʔ
  35. ϛυϧ΢ΣΞɾ֎෦αʔϏε ؔ࿈ w 3%#.4)%#$ )33 w &MBTUJDTFBSDICMPPEIPVOE w "84"1*BNB[POLB w

    (PPHMF"1*HPHPM w 'JSFCBTF͹Β͹Βͱଘࡏ͢Δ͕ࠓ͸࢖Θͣ
  36. ϥΠϒϥϦ଍Γͳ͍ɾͳΜ͔ ໰୊͋ͬͨΈ͍ͨͳέʔε w ৽͍͠΋ͷʹؔ͢ΔରԠ w pSFCBTFGDNBENJOSFBMUJNFEC w CMPPEIPVOEͱ&MBTUJDTFBSDIͷWFSTJPO w ϚϧνόΠτରԠ

    w NJNFNBJMͱ೔ຊޠ w ۩ମ౓͕ߴ͍ɾมͳ༻్ w ࿨ྐྵ w όάͬͨDTW
  37. ·ͱΊ

  38. ·ͱΊ w ҆શ w ੩తܕ෇͚ɺ෭࡞༻ͷ෼཭ʹΑΓόά๷͙ w %#ͳͲͱͷ݁߹Ͱͷόά΋๷͙ w υΩϡϝϯτͱ࣮૷ͷᴥᴪΛى͜͞ͳ͍ w

    ߴ଎ w ந৅౓ͷߴ͍ɺσʔλɾϩδοΫΛදݱɾ࣮૷ w ࣗ໌ͳςετΛॻ͔ͳͯ͘ྑ͍ঢ়ଶʹ͢Δ w ܕʹΑΔ੍໿ʹΑΓɺίʔυϨϏϡʔͷίετΛԼ͛Δ w 3&1-ͳͲ΋࢖ͬͨॊೈͳ։ൃελΠϧ
  39. ·ͱΊ w ଟ͘ͷϝϦοτ͕༗Δ w ҰൠతͳϥΠϒϥϦ͸े෼ʹἧ͍ͬͯΔ w )BTLFMMͰ8FC"1*։ൃͰ͖Δ

  40. ࣭ٙԠ౴ )BTLFMM࢖͓͏ UXJUUFS!OBLBKJ@EBZP