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

関数型プログラミングと型システムのメンタルモデル

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.
Avatar for Naoya Ito Naoya Ito
October 26, 2023

 関数型プログラミングと型システムのメンタルモデル

Qiita Conference 2023 Autumun での発表資料です

発表時間の見積もりが下手で後半全然説明できませんでした、すみません!

実際のプロダクト開発ではどうすればいいのか? というケースは以下のスライドを参照してください。
(本スライドは、こちらのプロダクト開発の経験をベースに基礎を再整理したものになります)
https://speakerdeck.com/naoya/typescript-niyoru-graphql-batukuendokai-fa-75b3dab7-90a8-4169-a4dc-d1e7410b9dbd

Avatar for Naoya Ito

Naoya Ito

October 26, 2023
Tweet

More Decks by Naoya Ito

Other Decks in Programming

Transcript

  1. ͳͥ͜ͷ࿩ • ࡢࠓͷϓϩάϥϛϯάݴޠʹ͓͚ΔʮܕʯΛͲ͏ଊ͑Δ͔ – ͔͍͘͏ࢲ΋ɺ೥୅ࠒ͸ʮܕ෇͚ΊΜͲ͍͘͞ͳʔʯͱࢥ͍ͬͯͨ – ࠷ۙ͸ɺ౰࣌ͱ͸શ͘ҟͳΔϝϯλϧϞσϧΛ͍࣋ͬͯΔ • ϓϩάϥϛϯάݴޠɺϑϨʔϜϫʔΫʹ͓͚Δؔ਺ܕϓϩάϥϛϯά͔ΒͷӨڹ •

    )BTLFMMΛझຯͰॻ͘Α͏ʹͳͬͯɺϝϯλϧϞσϧ͕ߋ৽͞Εͨ – ੩తܕ෇͚ɺܕਪ࿦ɺؔ਺ܕϓϩάϥϛϯάɺจ຺ܭࢉʜ – ͳ͓ࠓ೔ͷ࿩͸ )BTLFMMಛ༗ͷ࿩Ͱ͸͋Γ·ͤΜɻͦͷͨΊओʹ 5ZQF4DSJQUͷྫ΋ަ͑ͯ࿩͠·͢
  2. ҉໧తͳঢ়ଶมԽ͕ݮΓɺϓϨθϯςʔγϣϯΛએݴతʹهड़Ͱ͖ΔΑ͏ʹͳͬͨ import { useState } from 'react'; export default function

    MyApp() { const [count, setCount] = useState(0); function handleClick() { setCount(count + 1); } return ( <div> <h1>Counters that update together</h1> <MyButton count={count} onClick={handleClick} /> <MyButton count={count} onClick={handleClick} /> </div> ); +BWB4DSJQU
  3. update : Msg -> Model -> ( Model, Cmd Msg

    ) update msg model = case msg of ToggleLike -> ( { model | photo = Maybe.map toggleLike model.photo }, Cmd.none ) UpdateComment comment -> ( { model | photo = Maybe.map (updateComment comment) model.photo }, Cmd.none ) SaveComment -> ( { model | photo = Maybe.map saveNewComment model.photo }, Cmd.none ) LoadFeed (Ok photo) -> ( { model | photo = Just photo }, Cmd.none ) LoadFeed (Err _) -> ( model, Cmd.none ) viewLikeButton : Photo -> Html Msg viewLikeButton model = let buttonClass = if model.liked then ... div [ class "like-button" ] [ i [ class "fa fa-2x", class buttonClass, onClick ToggleLike ] [] ] &MN 7JFX͸ .PEFMΛඳըɻ Ϣʔβʔૢ࡞ʹԠͯ͡Πϕ ϯτΛૹΔͱŋŋŋ &MNϥϯλΠϜ͕ VQEBUFؔ਺ ΛݺͿɻؔ਺ʹ͸ΠϕϯτʹԠ ͨ͡Ϟσϧͷঢ়ଶભҠΛؔ਺Ͱ هड़͢Δ &MN
  4. 𝑠 = 1 + 2 + 3 + … +

    n • Ͳ͏ॻ͘  ࠷ۙݟ͔͚ͨ – GPSจ खଓతɺ໋ྩܕ – ౳ࠩ਺ྻͷެࣜ – ࠶ؼɺ৞ΈࠐΈ એݴతɺؔ਺ܕ
  5. GPSจͰॻ͘ • ஝͑ΒΕ͍ͯΔ஋Λॻ͖׵͑Δ͜ͱΛ܁Γฦͯ͠ɺͦͷ஋͔Β݁ՌΛಘΔ • ݱࡏͷίϯϐϡʔλɾΞʔΩςΫνϟͷܭࢉϞσϧʹ͍ۙ – ϝϞϦ͔ΒϨδελʹσʔλΛϩʔυ͠ɺԋࢉΛ࣮ߦͯ͠ɺϝϞϦʹॻ͖ग़͢ int total =

    0; for (int i = 1; i <= n; i++) { total += i; } ͱ͜ΖͰɺզʑ͸ίϯϐϡʔλΛ࢖ͬͯܭࢉΛ͍ͯ͠Δ͕ɺϓϩάϥϛϯά্ͷܭࢉϞσϧ·ͰͦΕʹ฿͏ ͜ͱ͸ඞਢͳͷ͔ 
  6. Ҿ਺ʹؔ਺Λద༻͢Δ͜ͱΛ࠶ؼ ؔ਺ݺͼग़͠ Ͱ܁Γฦ͠ɺ஋ΛಘΔ sum [] = 0 sum (x :

    xs) = x + sum xs -- 関数 sum を再帰的に呼び (+) 関数を適用 )BTLFMM const sum = (ns: number[]): number => { if (ns.length == 0) return 0 const [x, ...xs] = ns return x + sum(xs) } 5ZQF4DSJQU
  7. ஋Λॻ͖׵͑ΔͷͰ͸ͳ͘ɺؔ਺ͷ໭Γ஋ʹؔ਺Λ࠶ؼతʹద༻ͯ͠஋ΛಘΔ f a b = a + b main =

    do print $ f 10 (f 9 (f 8 (f 7 (f 6 (f 5 (f 4 (f 3 (f 1 2)))))))) )BTLFMM
  8. ʮ໭Γ஋ʹ܁Γฦؔ͠਺Λద༻͢ΔʯΛؔ਺ʹͨ͠ͷ͕ GPME΍ SFEVDF • ؔ਺Λద༻͢Δ͜ͱͰ஋ΛಘΔ͜ͱʹΑͬͯܭࢉΛ੒͢ͷ͕ɺؔ਺ܕϓϩάϥϛϯάͷߟ͑ํ • ࠜఈʹ͸ϥϜμܭࢉ uuuࠓ೔͸ͦͷ࿩͸͠ͳ͍ let s

    = foldl (+) 0 [1 .. n] )BTLFMM let s = [1, 2, 3, 4, 5].reduce((acc, i) => acc + i, 0)``` let s = [1, 2, 3, 4, 5].reduce((acc, i) => acc + i, 0) 5ZQF4DSJQU
  9. จɺࣜ • จ 4UBUFNFOU – GPSจɺ JGจɺQSJOUจ  – ܭࢉػ΁ͷԿ͔͠Βͷಈ࡞໋ྩɺखଓ͖ɻ஋Λฦ͞ͳ͍

    • ࣜ &YQSFTTJPO – ʮܭࢉΛ࣮ߦͯ݁͠ՌΛಘΔΑ͏ͳॲཧΛهड़͢ΔͨΊͷจ๏ཁૉʯ 8JLJQFEJB – ඞͣ஋Λฦ͢ – ؔ਺ܕϓϩάϥϛϯάʹ͓͚Δؔ਺͸ࣜ
  10. ࠶ܝ GPSจͰॻ͘ int total = 0; for (int i =

    1; i <= n; i++) { total += i; } • GPSจͱ୅ೖจͰɺ܁Γฦ͠ԋࢉ݁ՌΛॻ͖ࠐΉ ୅ೖ͢Δ ໋ྩΛߦ͍ͬͯΔ • ܭࢉػ΁ͷ໋ྩ uuu໋ྩܕ • จͰܭࢉΛߏ੒͢Δͱɺ໋ྩతʹͳΔ
  11. ࠶ܝ ࠶ؼతʹؔ਺Λద༻͢Δ • ࣜʹΑΓܭࢉΛએݴ͢Δ • ࣜ͸ඞͣ஋Λ໭͢ɻͦͷ஋ʹ࠶ͼؔ਺Λద༻͢Δ • ࣜͰܭࢉΛߏ੒͢ΔͱɺએݴతʹͳΔ let s

    = foldl (+) 0 [1 .. n] )BTLFMM let s = [1, 2, 3, 4, 5].reduce((acc, i) => acc + i, 0)``` let s = [1, 2, 3, 4, 5].reduce((acc, i) => acc + i, 0) 5ZQF4DSJQU
  12. customer.archive() 5ZQF4DSJQU const archived = archiveCustomer(customer) 5ZQF4DSJQU • ໋ྩతʹॻ͘ –

    ΦϒδΣΫτͷ಺෦ঢ়ଶΛॻ͖׵͑Δ໋ྩΛߦ͏͜ͱͰɺঢ়ଶΛมԽͤ͞Δ – ঢ়ଶͷมԽ͕҉໧త • ؔ਺తʹॻ͘ – Ҿ਺ͷΦϒδΣΫτʹؔ਺Λద༻ͯ͠ɺঢ়ଶભҠޙͷΦϒδΣΫτΛಘΔ – ભҠલͷঢ়ଶ͸ඞͣҾ਺ʹݱΕɺભҠޙͷঢ়ଶ͸໭Γ஋ʹݱΕΔɻঢ়ଶมԽ͕໌ࣔత
  13. 8FCΞϓϦέʔγϣϯͱ *0 • 8FCΞϓϦέʔγϣϯ։ൃͷଟ͘ͷ෦෼͸ɺίϯϐϡʔλ ֎ք ͱͷ΍ΓͱΓ – σʔλϕʔε͔ΒσʔλΛऔಘͯ͠ *0 –

    8FC"1*Λίʔϧͯ͠ *0 – ୺຤ʹग़ྗ͢Δ *0 – *0͸ίϯϐϡʔλ΁ͷ໋ྩͳͷͰɺ໋ྩతʹهड़͢Δͷ͸ࣗવ Ͱ΋ΞϓϦέʔγϣϯ͕େ͖͘ͳͬͯ͘Δͱʜ IO -> ܭࢉ (ۀ຿ϩδοΫɺঢ়ଶભҠ) -> IO ͷਅΜதͷ෦෼͕େ͖͘ɺෳࡶʹͳ͖ͬͯ·ͤΜ͔
  14. update : Msg -> Model -> ( Model, Cmd Msg

    ) update msg model = case msg of ToggleLike -> ( { model | photo = Maybe.map toggleLike model.photo }, Cmd.none ) UpdateComment comment -> ( { model | photo = Maybe.map (updateComment comment) model.photo }, Cmd.none ) SaveComment -> ( { model | photo = Maybe.map saveNewComment model.photo }, Cmd.none ) LoadFeed (Ok photo) -> ( { model | photo = Just photo }, Cmd.none ) LoadFeed (Err _) -> ( model, Cmd.none ) ࠶ܝ &MN &MN
  15. *0ঢ়ଶભҠ *0 model -> model' *0 JOQVUMPBE *0 PVUQVU *0ͱ੾Γ཭ͤ͹ɺ͜͜Λίϯϐϡʔλ

    ΁ͷ໋ྩͰ͸ͳ͘ɺʮܭࢉʯͱͯ͠એ ݴ͢Δ͜ͱ΋Ͱ͖Δɻ͜͜ͷঢ়ଶ؅ཧ Λ͍͍ײ͡ʹͰ͖Ε͹
  16. ΦχΦϯΞʔΩςΫνϟ ͳͲ Ͱಘ͍ͨ͜ͱ • ςελϏϦςΟ͕޲্͢Δ ෦඼ΛೖΕସ͑ՄೳʹͳΔ – ͦΕ͸ͦ͏ɻͰ΋ɺ෭࣍తͳ΋ͷͰ͋ͬͯओ໨తͰ͸ͳ͍ • ۀ຿ϩδοΫΛ

    *0͔Β੾Γ཭͠ɺܭࢉػ΁ͷ໋ྩͰ͸ͳ͘७ਮͳϩδοΫ ܭࢉ ͱͯ͠ߟ ͑ΒΕΔΑ͏ʹ͍ͨ͠ – ৭ʑͳύϥμΠϜΛద༻Ͱ͖ΔՄೳੑ͕ੜ·ΕΔ • ΦϒδΣΫτࢦ޲Ͱ΋ྑ͍͠ɺखଓܕͰ΋ྑ͍͠ɺؔ਺ܕϓϩάϥϛϯάͰ΋ྑ͍ • ͏ͪɺએݴతʹঢ়ଶ؅ཧ͢Δͷ͸ɺ ݱ࣌఺Ͱ͸ ྑ͍ϓϥΫςΟεͰ͸ͳ͍͔ ˡ ࠓ͜͜
  17. ୤ઢ จΛ࢖͏ͱ͔ͦ͜ΒҶͮΔࣜతʹ໋ྩܕʹͳΔ • )BTLFMMͷ forM_ ࣜ ··· for จΈ͍ͨͳ΋ͷ (※࣮ࡍ͸จͰ͸ͳ͘ϢχοτܕΛฦࣜ͢)

    – ϛϡʔλϒϧͳ഑ྻΛॻ͖׵͑ͨΓɺܭࢉػͱೖग़ྗ͢Δͱ͖ʹ࢖͏ – ܭࢉػ΁ͷ໋ྩతͳࣜͳͷͰ໭Γ஋͕ͳ͍ – ͳ͓ )BTLFMM͔ͩΒͱ໋͍ͬͯྩతʹॻ͚ͳ͍Θ͚Ͱ͸ͳ͍͠ɺ໋ྩతʹهड़͢Δํ͕ྑ͍৔߹΋Α͋͘Δ main = do arr <- newListArray @IOArray (1, 10) [1 .. 10] forM_ [1 .. 10] $ ¥i -> do x <- readArray arr i writeArray arr i (x * 2) forM_ [1 .. 10] $ ¥i -> do readArray arr i >>= print )BTLFMM
  18. ಉ͡໨తͷσʔλߏ଄ͷΠϛϡʔλϒϧ൛ɺϛϡʔλϒϧ൛Λ࢖͏ൺֱ main = do [n, m] <- getInts uvs <-

    replicateM m getTuple let uf0 = newUF (0, n - 1) -- 関数 f により uf を次の状態に遷移させる let (_, xs) = mapAccumL f uf0 uvs where f uf (u, v) = let same = isSame uf u v in if same then (uf, same) else (unite uf u v, same) … -- 状態の表現にイミュータブルなデータ構造 data UnionFind = UnionFind { parent :: IM.IntMap Int, size :: IM.IntMap Int } deriving (Show) )BTLFMM -- 状態の表現にミュータブルな配列 data UnionFind a v = UnionFind (a v v) (IOUArray v Int) )BTLFMM main = do [n, m] <- getInts uvs <- replicateM m getTuple uf <- newUF @IOUArray (0, n - 1) (-1) forM_ uvs $ ¥(u, v) -> do same <- isSame uf u v -- データ構造 uf に作用を起こして内部状態を変える unless same $ do unite uf u ϛϡʔλϒϧͳσʔλߏ଄Λ࢖͏ͱ஋ Λ໭͞ͳ͍ͷͰɺ੍ޚߏ଄΋ؚΊࣗવ ͱ໋ྩܕͷ࣮૷ʹͳΔ ͪͳΈʹࢲ͸ 6OJPO'JOE͸ͪ͜ΒΛ ৗ༻ͯ͠·͢ ؔ਺ͷ໭Γ஋͕࣍ͷঢ়ଶͷσʔλߏ଄ ͳͷͰɺ໭Γ஋ΛҾ͖ճؔ͢਺ܕతͳ ࣮૷ʹͳΔ
  19. • ʮܕ͸ɺޓ͍ʹؔ࿈͢Δ஋ͷू߹Ͱ͢ʯ ϓϩάϥϛϯά )BTLFMM • ʮܕ UZQF ͋Δ͍͸σʔλܕ EBUBUZQF ͱ͸ɺσʔλ͕ͲͷΑ͏ͳੑ࣭ͷू߹ʹଐ͢Δ

    ͔Λࣔ͢΋ͷͰ͢ʯ ؔ਺ܕϓϩάϥϛϯά࣮ફೖ໳ • ʮ Մೳͳૢ࡞΍ԋࢉͳͲͷମܥͳͲ͕ ڞ௨͍ͯ͠Δ஋ͷू߹͕ܕͰ͋ΓɺͦΕͧΕͷ஋͸ ෳ਺ͷू߹ ܕ ʹଐ͢͜ͱ͕Ͱ͖Δʯ 5ZQF4DSJQUʹ͓͚Δܕͷू߹ੑͱ֊૚ੑ • ʮܕ͸஋΍ॲཧͷຬͨ͢΂͖ੑ࣭Λڧ͘ҙຯ෇͚͢ΔͨΊʹ࢖͏͜ͱ͕Ͱ͖ɺʮϓϩάϥϜ ͷਖ਼͠͞ʯΛอূ͢ΔͨΊͷॏཁͳϑΝΫλʔͰ͢ʯ
  20. export function toColor(value: string): Result<Color, ValidationError> { return /^#[0-9a-f]{3}([0-9a-f]{3})?$/i.test(value) ?

    ok(value as Color) : err(new ValidationError('⾊の値が不正です。#FFFFFF形式で指定してください')) } 5ZQF4DSJQU ܕ͸ߏ଄Խ͢Δ͜ͱ͕Ͱ͖Δ
  21. ୅਺తσʔλܕ • )BTLFMMͳͲͷݴޠͰ͸৽͍͠σʔλߏ଄Λఆٛ͢Δͷʹ୅਺తσʔλܕͰදݱ͢Δ • ܕΛ૊Έ߹ΘͤΔͷʹ࿦ཧੵ "/% ͚ͩͰͳ͘ ࿦ཧ࿨ 03 ͕࢖͑Δ

    data Bool = True | False data Maybe a = Nothing | Just a )BTLFMM )BTLFMM data UnionFind = UnionFind { parent :: IM.IntMap Int, size :: IM.IntMap Int } )BTLFMM
  22. ܕͷ૊Έ߹Θͤʹʮ࿨ 03 ʯ͕࢖͑Δ • ৽͍͠σʔλߏ଄ͷܗΛએݴ͢Δखஈ͸֤ݴޠ༷ʑͰ͋Δ͕ɺ͔ͭͯଟ͘ͷݴޠͰ͸ੵ "/% Ͱ૊Έ߹ ΘͤΔͷ͕ओͳํ๏ͩͬͨ – TUSVDU΍

    DMBTTͳͲϨίʔυܕʹΑΔϓϩύςΟͷ૊Έ߹Θͤ͸ "/% • "/%͚ͩͰܕͱܕΛ૊Έ߹ΘͤΔͱɺෆࣗવͳ֊૚΍ෆඞཁͳ஋ͷ૊Έ߹Θ͕ͤൃੜ͠΍͍͢ – ௚ੵͷ֊૚ߏ଄ uuuྫ͑͹ DMBTTʹΑΔ֊૚ߏ଄ data Bool = True | False )BTLFMM
  23. export interface ReservationHolder { kind: 'ReservationHolder' name: string nameKana: string

    | null phoneNumber: PhoneNumber email: EmailAddress | null } export interface Visitor { kind: 'Visitor' name: string nameKana: string | null phoneNumber: PhoneNumber } interface HolderAndVisitor { kind: 'HolderAndVisitor' holder: ReservationHolder visitor: Visitor } interface HolderOnly { kind: 'HolderOnly' holder: ReservationHolder } interface VisitorOnly { kind: 'VisitorOnly' visitor: Visitor } export type ReservationGuest = HolderAndVisitor | HolderOnly | VisitorOnly 5ZQF4DSJQU ߏ଄͕ҟͳΔ΋ͷΛʮ·ͨ͸ ࿨ 03 ʯͰ૊Έ߹ΘͤΔ
  24. l.BLJOHJMMFHBMTUBUFTVOSFQSFTFOUBCMFz interface User { memberId: MemberId | undefined guestId: GuestId

    | undefined } interface Member { userId: MemberId } interface Guest { guestId: GuestId } type User = Member | Guest औΓಘΔ஋ͷछྨ਺͸֤ଐੑͷੵʹͳΔ ௚ੵ Y ɾ྆ํ VOEFGJOFE ɾ྆ํͷ஋͕ຒ·Δ ͱ͍͏࢓্༷͋Γಘͳ͍ঢ়ଶ͕ੜ·ΕΔ औΓಘΔछྨ਺͸֤ଐੑͷ࿨ ௚࿨   ࢓্༷͋Γಘͳ͍ঢ়ଶ͸දݱ͠ͳ͍ ˠ ͦͯ͠ίϯύΠϥ͕ͦΕΛཧղ͢Δ Ϩίʔυ͸ʮ͔ͭ "/% ʯ ϢχΦϯ͸ʮ·ͨ͸ 03 ʯ 5ZQF4DSJQU 5ZQF4DSJQU
  25. type connection_state = | Connecting | Connected | Disconnected type

    connection_info = { state: connection_state; server: inet_addr; last_ping_time: time option; last_ping_id: int option; session_id: string option; when_initiated: time option; when_disconnected: time option; } type connecting = { when_initiated: time; } type connected = { last_ping : (time * int) option; session_id: string; } type disconnected = { when_disconnected: time; } type connection_state = | Connecting of connecting | Connected of connected | Disconnected of disconnected type connection_info = { state: connection_state; server: inet_addr; } 「なぜ次に学ぶ言語は関数型であるべきか - YAMAGUCHI::weblog」 より引用 https://ymotongpoo.hatenablog.com/entry/20111105/1320506449 0$BNM 0$BNM
  26. ͪ͜ΒΑΓ΋ŋŋŋ export class Tag { state: 'Unvalidated' | 'Validated' |

    'Created', id: TagId | undefined, groupId: RestaurantGroupId, label: string, icon: TagIcon | undefined, sortOrder: number | undefined, builtin: boolean | undefined } 5ZQF4DSJQU
  27. interface UnvalidatedTag { kind: 'Unvalidated' groupId: string label: string icon?:

    { symbol: string; type: TagIconType; color?: string | null | undefined } | null | undefined } interface ValidatedTag { kind: 'Validated' groupId: RestaurantGroupId label: string icon: TagIcon } export interface CreatedTag { kind: 'Created' id: TagId groupId: RestaurantGroupId label: TagLabel icon: TagIcon sortOrder: number builtin: boolean } export type Tag = UnvalidatedTag | ValidatedTag | CreatedTag ͪ͜Βͷํ͕ɺ஋ͷ૊Έ߹Θͤύλʔϯ͕গͳ͘ݫີ 5ZQF4DSJQU
  28. ࿨Ͱ૊Έ߹Θͤͯߏஙͨ͠΋ͷ͸ɺύλʔϯϚονͰ෼ղ main = do let someValue :: Maybe String someValue

    = ... case someValue of Just s -> putStrLn (s ++ ", naoya") Nothing -> putStrLn "Farewell" data Maybe a = Nothing | Just a )BTLFMM )BTLFMM +VTU4USJOH͔ /PUIJOHͷͲͪΒ͔ .BZCFܕΛύλʔϯϚονͰ෼ղ͢Δ
  29. 5ZQF4DSJQUͰ΋͍͚·͢ interface Empty { kind: "Empty" } interface Cons<T> {

    kind: "Cons" head: T tail: List<T> } export type List<T> = Empty | Cons<T> data List a = Empty | Cons a (List a) 5ZQF4DSJQU )BTLFMM ϦςϥϧܕͰλάΛ͚͓ͭͯ͘ ϢχΦϯͰ૊Έ߹Θͤͨܕ
  30. // List<T> への map 関数を実装 type map = <T, U>(f:

    (a: T) => U, xs: List<T>) => List<U> export const map: map = (f, xs) => { switch (xs.kind) { case "Empty": return Empty() case "Cons": return Cons(f(xs.head), map(f, xs.tail)) default: assertNever(xs) } } export function assertNever(_: never): never { throw new Error() } console.log(map(i => i * 2, myList)) 5ZQF4DSJQU λάʹԠͯ͡෼ղ ϦςϥϧܕͳͷͰͪΌΜͱܕ͕ޮ͘
  31. ྫ͑͹ಈతܭը๏ φοϓβοΫ໰୊ ͷ࣮૷ for (int j = 0; j <=

    W; ++j) dp[0][j] = 0; for (int i = 0; i < N; ++i) { for (int j = 0; j <= W; ++j) { if (j >= w[i]) dp[i+1][j] = max(dp[i][j-w[i]] + v[i], dp[i][j]); else dp[i+1][j] = dp[i][j]; } } cout << dp[N][W] << endl; let f (w, v) (wi, vi) | v == minBound = [(w, v)] | otherwise = [(w, v), (w + wi, v + vi)] let dp = accumArrayDP @UArray f max minBound (0, wx) [(0, 0)] wvs print $ maximum (elems dp) )BTLFMM $ ू߹ʹԋࢉͭͱ୯ҐݩΛೖΕΕ͹ %1ʹͳΔΑ͏ந৅Խ͍ͯ͠ Δ %1͸൒؀
  32. • ΞϧΰϦζϜΛ୅਺తߏ଄Λҙࣝͯ͠ந৅Խ͢Δɻʮ͜ͷΞϧΰϦζϜ ܭࢉߏ଄ ʹͲΜͳ݁߹ԋࢉΛೖ Εͯ࢖͏͔ʯͱ͍͏ΠϯλϑΣʔεͷؔ਺͕ಘΒΕΔ • ͲΜͳԋࢉΛೖΕΒΕΔ͔ uuuܕ͕อূ͢Δ ೖΕΒΕΔԋࢉͷू߹Λఆٛ͢Δ let

    sections = shakutori (1, n) (s !) (+) (-) 0 (¥acc r -> acc + r <= k) let s = scanl' (+) 0 xs let dp = doubling f (+) (10 ^ 5, 10 ^ 18) xs ͠Ό͘ͱΓ๏ μϒϦϯά ྦྷੵԋࢉ
  33. ࠶ܝ ਤ͸ԿΛݴ͍ͬͯΔ͔ • ϓϩάϥϜΛʮܭࢉػ΁ͷ໋ྩʯͰ͸ͳ͘ʮؔ਺Λద༻ͯ͠஋ΛಘΔܭࢉʯͷఆٛͱଊ͑Δ • ؔ਺ G͸ɺ஋Λࣸ͢΋ͷ • ͲΜͳू߹͔ΒͲΜͳू߹ʹࣸ͞ΕΔ͔ɻͦͷू߹ΛܕͰදݱ͢Δ •

    ू߹ͷදݱɺͭ·ΓʮܕͱܕΛ૊Έ߹Θͤͨߏ଄Խʯ͕ΑΓྑ͘Ͱ͖Ε͹ɺϓϩάϥϜ͕ݎ࿚ʹͳΔ ࠷ۙ͸͜ͷߟ͑Λத৺ʹஔ͍ͯɺϓϩάϥϜઃܭΛ͍ͯ͠·͢ ʮू߹Ͱ͋ΔܕͰઃܭ͠ɺؔ਺Ͱঢ়ଶΛભҠʯ
  34. ͲΜͳϓϩάϥϛϯάݴޠͰ΋ؔ਺ܕͰΨϯΨϯ΍͍ͬͯ͘΂͖ • ๯಄ʹ΋ड़΂ͨ௨Γɺؔ਺ܕϓϩάϥϛϯά࠷ڧɺͱ͍͏࿩͸͍ͯ͠·ͤΜ • Αͬͯɺࢲݟ͸ʮ͍͍͑ʯݴޠͷಛੑʹ߹Θͤ·͠ΐ͏ – )BTLFMMɺ 'ɺ 0$BNMɺ4DBMBͳͲͦ͏͢Δ͜ͱΛલఏʹ࡞ΒΕ͍ͯΔݴޠ͸໰୊ͳ͍Ͱ͠ΐ͏ –

    5ZQF4DSJQUuuuؔ਺ܕͱͯ͠ͷଆ໘͸͋Γ·͕͢ɺγϯλοΫε໘Ͱ͸લஈͷݴޠʹൺֱ͢Δͱෆ଍΋ײ͡·͢ɻ Ұํ 54ͷܕγεςϜ͸ɺ͝ଘ஌ͷ௨Γಈతͳಛ௃΋͋ΓɺඇৗʹڧྗͰ͢ɻܕ͸ू߹ͷϝϯλϧϞσϧͰ্ख ʹ࢖͍ɺؔ਺ܕͷΤοηϯεΛऔΓೖΕͭͭ΋ɺ໋ྩతʹॻ͚͹͍͍৔໘Ͱ͸ແཧΛ͠ͳ͍uuu͙Β͍͕ྑ͍όϥ ϯεͰ͸ͳ͍Ͱ͠ΐ͏͔ • ࢲ͸ 3FTVMUܕΛ࢖ͬͯؔ਺ܕدΓͰ΍͍ͬͯ·͕͢ɺ͍͍ଆ໘΋͋Γ·͕͢໘౗ͳ͜ͱ΋͋Γ·͢ – 3VTUɺ,PUMJOɺ4XJGUuuuܕʹʮ03ʯ૬౰ͷػೳ͕͋ΓɺܕγεςϜ͸ݱ୅తͰ͢ɻͲΜͳελΠϧ͕͍͍͔͸ɺ ৄ͘͠ͳ͍ͷͰΘ͔Γ·ͤΜɻ֤ݴޠͳΓͷʮ˓˓ 8BZʯ͕͋Δͱࢥ͍·͢ɺࣝऀʹ͓ฉ͖͍ͩ͘͞
  35. ࢀߟจݙ • 8JMM,VSUஶ גࣜձࣾΫΠʔϓ ༁ ʮೖ໳ )BTLFMMϓϩάϥϛϯάʯ ᠳӭࣾ  •

    (SBIBN)VUUPOஶ ࢁຊ࿨඙ ༁ ʮϓϩάϥϛϯά )BTLFMMୈ൛ʯ ϥϜμϊʔτ  • 4DPUU8MBTDIJOஶ ʮ%PNBJO.PEFMJOH.BEF'VODUJPOBMʯ  • +FSFNZ'BJSCBOL ஶ ϠΪͷ͘͞ΒͪΌΜ ຋༁ ʮϓϩάϥϛϯά&MNᴷ҆શͰϝϯςφϯε͠΍ ͍͢ϑϩϯτΤϯυΞϓϦέʔγϣϯ։ൃೖ໳ʯ ϚΠφϏग़൛  • େ઒ಙ೭ஶ ʮ<૿ิվగ>ؔ਺ϓϩάϥϛϯά࣮ફೖ໳ʯ ٕज़ධ࿦ࣾ  • 8FCͷϦιʔε – 5ZQF4DSJQUʹ͓͚Δܕͷू߹ੑͱ֊૚ੑ IUUQT[FOOEFWFTUSBBSUJDMFTUZQFTDSJQUUZQFTFUIJFSBSDIZ – ʮͳͥ࣍ʹֶͿݴޠ͸ؔ਺ܕͰ͋Δ΂͖͔  :"."(6$)*XFCMPHʯ  IUUQTZNPUPOHQPPIBUFOBCMPHDPNFOUSZ