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

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

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

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

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

Daishi Nakajima

November 10, 2018
Tweet

More Decks by Daishi Nakajima

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

  4. )BTLFMMͷ༻్

    View Slide

  5. )BTLFMMͷ༻్
    w #BDLFOE 8FC"1*#BUDI
    ͷ։ൃ
    w Ұൠతͳ8ϞόΠϧΞϓϦ
    w ௚ۙ
    w ՝ۚͷ͋Δ4/4ʢ#&ਓ݄ఔ౓ʣ

    View Slide

  6. ٕज़ελοΫ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  13. 4FSWBOU
    "1*ͷܕ
    શମ͕ܕͰܨ͕ͬͨঢ়ଶ
    3FRVFTU
    %#
    )33
    )BOEMFS
    4FSWJDF
    7JFX
    3FTQPOTF
    &OUJUZ
    )551
    2VFSZ
    ܕͷ֎ͷੈք
    ܕͷ֎ͷੈք
    Y
    ઃܭ্ͷ੍໿
    υΩϡϝϯτ౳ͷੜ੒

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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ఆٛͱ࣮૷ͷҰக͕อূ͞Ε͍ͯΔ

    View Slide

  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

    View Slide

  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

    View Slide

  20. ܕΫϥε
    w 5P+40/'SPN+40/+40/ʹม׵Մೳ
    w %FGBVMUσϑΥϧτͷ஋Λੜ੒Մೳ
    w 5P4DIFNB4XBHHFSυΩϡϝϯτʹม׵Մೳ
    w "SCJUSBSZϥϯμϜͳ஋Λੜ੒Մೳ
    w -FOTHFUUFSTFUUFS

    View Slide

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

    View Slide

  22. TXBHHFS NPDL౳ͷੜ੒
    w "1*ఆ͔ٛΒੜ੒
    w 4XBHHFS
    w TFSWBOUTXBHFS
    w ࣮૷ͱυΩϡϝϯτ͕ͣΕͳ͍ݴޠͷྗΛ࢖͑Δ
    w ϞοΫαʔόʔ
    w TFSWBOUNPDL
    w "SCJUSBSZ 2VJDL$IFDL

    View Slide

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

    View Slide

  24. )BOEMFSͷ֦ு
    w )BOEMFSʹඞཁͳϞφυΛ߹੒͢Δ
    newtype AppM a = AppM
    { runAppM :: ReaderT Context Handler a
    } deriving (...)
    3FBEFS
    άϩʔόϧʹࢀর͢Δ஋Λѻ͏
    ઃఆ஋ɺ$POOFDUJPO1PPM 5SBOTBDUJPO؅ཧ ౳

    3FBEFSΛ߹੒

    View Slide

  25. ܕͰઃܭ্ͷ੍໿Λߦ͏
    w DMBTT
    .POBE4FSWJDFN
    w ෭࡞༻࣮ߦՄೳ %#΁ͷΞΫηεՄೳ )551తͳྫ֎
    ౤͛ͨΓ͸Ͱ͖ͳ͍
    w DMBTT ʜ
    .POBE7JFXN
    w ઃఆ஋ͷࢀর͸Մೳ ෭࡞༻ى͜͞ͳ͍

    View Slide

  26. ܕͰઃܭ্ͷ੍໿Λߦ͏
    queryM :: MonadService m => a -> m b

    renderUser :: MonadView m => User -> m UserView
    renderUser x = do
    imgs <- queryM UserImages x

    ίϯύΠϧΤϥʔ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  30. 3&1-ͰԥΔ
    > runAppM’ $ postMessagesR $
    def & text .~ “hello”
    Right (Message {_id = 123, _userName =
    “hoge”, image=…
    postMessagesR :: PostMessageBody -> AppM Message
    ࣍ͷ)BOEMFSʢΤϯυϙΠϯτʣΛςετ͍ͨ͠
    HIDJͰ؆୯ʹ࣮ߦ

    View Slide

  31. 4FSWBOU
    "1*ͷܕ
    શମ͕ܕͰܨ͕ͬͨঢ়ଶ
    3FRVFTU
    %#
    )33
    )BOEMFS
    4FSWJDF
    7JFX
    3FTQPOTF
    &OUJUZ
    )551
    2VFSZ
    ܕͷ֎ͷੈք
    ܕͷ֎ͷੈք
    Y
    ઃܭ্ͷ੍໿
    υΩϡϝϯτ౳ͷੜ੒

    View Slide

  32. શମ͕ܕͰܨ͕ͬͨঢ়ଶ
    w ୯७ͳόάΛ๷͙ɻ
    w ࣗ໌ͳςετΛॻ͘ඞཁ͕ͳ͍ɻ
    w ϩδοΫʹूத
    w ྫ͸3%#)33͕ͩɺ)BTLFMMͰ͸Ϩϕϧͷࠩ͸͋ΕͲɺ
    ຆͲͷϥΠϒϥϦ͕ܕ҆શͰ͋Δ܏޲͕͋Δɻ

    View Slide

  33. ར༻ϥΠϒϥϦͷ
    ֓ཁ

    View Slide

  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
    ϩΨʔ

    View Slide

  35. ϛυϧ΢ΣΞɾ֎෦αʔϏε
    ؔ࿈
    w 3%#.4)%#$ )33
    w &MBTUJDTFBSDICMPPEIPVOE
    w "84"1*BNB[POLB
    w (PPHMF"1*HPHPM
    w 'JSFCBTF͹Β͹Βͱଘࡏ͢Δ͕ࠓ͸࢖Θͣ

    View Slide

  36. ϥΠϒϥϦ଍Γͳ͍ɾͳΜ͔
    ໰୊͋ͬͨΈ͍ͨͳέʔε
    w ৽͍͠΋ͷʹؔ͢ΔରԠ
    w pSFCBTFGDNBENJOSFBMUJNFEC
    w CMPPEIPVOEͱ&MBTUJDTFBSDIͷWFSTJPO
    w ϚϧνόΠτରԠ
    w NJNFNBJMͱ೔ຊޠ
    w ۩ମ౓͕ߴ͍ɾมͳ༻్
    w ࿨ྐྵ
    w όάͬͨDTW

    View Slide

  37. ·ͱΊ

    View Slide

  38. ·ͱΊ
    w ҆શ
    w ੩తܕ෇͚ɺ෭࡞༻ͷ෼཭ʹΑΓόά๷͙
    w %#ͳͲͱͷ݁߹Ͱͷόά΋๷͙
    w υΩϡϝϯτͱ࣮૷ͷᴥᴪΛى͜͞ͳ͍
    w ߴ଎
    w ந৅౓ͷߴ͍ɺσʔλɾϩδοΫΛදݱɾ࣮૷
    w ࣗ໌ͳςετΛॻ͔ͳͯ͘ྑ͍ঢ়ଶʹ͢Δ
    w ܕʹΑΔ੍໿ʹΑΓɺίʔυϨϏϡʔͷίετΛԼ͛Δ
    w 3&1-ͳͲ΋࢖ͬͨॊೈͳ։ൃελΠϧ

    View Slide

  39. ·ͱΊ
    w ଟ͘ͷϝϦοτ͕༗Δ
    w ҰൠతͳϥΠϒϥϦ͸े෼ʹἧ͍ͬͯΔ
    w )BTLFMMͰ8FC"1*։ൃͰ͖Δ

    View Slide

  40. ࣭ٙԠ౴
    )BTLFMM࢖͓͏
    [email protected]

    View Slide