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

LayoutRule in Haskell (98)

wado
March 18, 2019

LayoutRule in Haskell (98)

wado

March 18, 2019
Tweet

Other Decks in Technology

Transcript

  1. ϨΠΞ΢τϧʔϧͱ͸ • Layout Rule ͸ Offside Rule ͱ΋ݴ͏ • Πϯσϯτͷ࢓ํʹΑͬͯϓϩάϥϜͷҙຯ͕มԽ͢Δ

    • ϨΠΞ΢τϧʔϧΛ࠾༻͍ͯ͠Δݴޠ • Haskell, Python, F#, YAML, Markdown, etc…
  2. ϨΠΞ΢τϧʔϧͷՄࢹԽ • ϒϨʔε ({ }) ͱηϛίϩϯ (;) Λૠೖ͢Δ͜ͱͰϨΠΞ΢ τϧʔϧΛՄࢹԽͰ͖Δ (ਖ਼֬ʹ͸ՄࢹԽͰ͸ͳ͘ม׵)

    • ͜ͷม׵͸ Haskell Language Report Ͱఆٛ͞Ε͍ͯΔ L ؔ਺ʹΑͬͯߦΘΕΔ • ͨͩ͠ɺLؔ਺ͷೖྗ͸௨ৗͷϓϩάϥϜͰ͸ͳ͘ laid- out ؔ਺ʹΑͬͯલॲཧ͕ߦΘΕͨ΋ͷ
  3. ۩ମྫ module AStack( Stack, push, pop, top, size ) where

    data Stack a = Empty | MkStack a (Stack a) push :: a -> Stack a -> Stack a push x s = MkStack x s size :: Stack a -> Int size s = length (stkToLst s) where stkToLst Empty = [] stkToLst (MkStack x s) = x:xs where xs = stkToLst s pop :: Stack a -> (a, Stack a) pop (MkStack x s) = (x, case s of r -> i r where i x = x) -- (pop Empty) is an error top :: Stack a -> a top (MkStack x s) = x -- (top Empty) is an error module AStack( Stack, push, pop, top, size ) where {data Stack a = Empty | MkStack a (Stack a) ;push :: a -> Stack a -> Stack a ;push x s = MkStack x s ;size :: Stack a -> Int ;size s = length (stkToLst s) where {stkToLst Empty = [] ;stkToLst (MkStack x s) = x:xs where {xs = stkToLst s }};pop :: Stack a -> (a, Stack a) ;pop (MkStack x s) = (x, case s of {r -> i r where {i x = x}}) -- (pop Empty) is an error ;top :: Stack a -> a ;top (MkStack x s) = x -- (top Empty) is an error } ม׵લ ม׵ޙ
  4. Indentation • indentation of a lexeme • lexeme ͷ࠷ॳͷจࣈͷྻ൪߸ •

    indentation of a line • ߦͷҰ൪ࠨ୺ʹग़ݱ͢Δ lexeme ͷ indentation • ࠷ॳͷྻ൪߸͸ 0 Ͱ͸ͳ͘ 1 ͔Β࢝ΊΔ • ཧ༝1: ϒϩοΫͷऴΘΓ < ϒϩοΫͷ࢝·Γ ͱ͍͏Πϯσϯτྔͷ৚݅Λຬͨͨ͢ ΊɻҰ൪֎ଆͷϨΠΞ΢τϒϩοΫΛด͡ΔͨΊʹඞཁɻ • ཧ༝2: Ϣʔβ͕໌ࣔతʹ { Λૠೖͨ͠ࡍʹΠϯσϯτྔ 0 ͱ͢ΔͨΊ • Ϣχίʔυจࣈ͸ ASCII จࣈͱಉ͡෯ͱͯ͠ॲཧ͞ΕΔ
  5. f = a + b ␣␣where ␣␣␣␣a = 100 ␣␣␣␣a

    = 200 1 5 9 1 2 3 4 Indentation of line 1 3 5 5 Indentation of lexeme f 1 = 3 a 5 + 7 b 9
  6. • ҎԼͷ׳शʹै͏ݻఆ෯ϑΥϯτΛར༻͍ͯ͠ΔͱԾఆ • *newline*, *return*, *linefeed*, *formfeed* ͸৽͍͠ߦΛ։ ࢝͢Δ •

    λϒετοϓ͸8จࣈ • λϒจࣈ͸ݱࡏͷҐஔ͔Β࣍ͷλϒετοϓ·Ͱɺྻ൪߸ Λௐ੔͢ΔͨΊʹඞཁͳे෼ͳྔͷεϖʔεΛૠೖ͢Δ • ৗʹ8จࣈͷεϖʔεΛ௥Ճ͢ΔΘ͚Ͱ͸ͳ͍
  7. Laidout • طଘͷ lexeme ʹ௥Ճ͞ΕΔτʔΫϯ • {n} τʔΫϯ • ৽࢝͘͠·Δ࣍ͷϒϩοΫͷΠϯσϯτྔΛද͢

    • {0} ͸ϑΝΠϧͷऴ୺Λද͢ • <n> τʔΫϯ • ߦͷΠϯσϯτྔΛද͢
  8. {n} τʔΫϯ • Rule1 • let, where, do, of ͷޙʹ

    { ͕དྷͳ͍৔߹ʹ {n} Λ lexeme ͷޙΖʹૠೖ͢Δ • n ͸࣍ͷ lexeme ·ͰͷΠϯσϯτྔ • ϑΝΠϧͷऴ୺ʹ౸ୡͨ͠৔߹͸ 0 • Rule2 • Ϟδϡʔϧͷ࠷ॳͷ lexeme ͕ { ·ͨ͸ module Ͱ͸ͳ͍৔߹ɺ{n} Λ lexeme ͷલʹ௥Ճ͢Δ • n ͸ lexeme ͷΠϯσϯτྔ
  9. f = id 2 {1}f = id 2{0} f =

    id n where n = 2 {1}f = id n where{9} n = 2{0} f = id n where n = 2 m = 3 {1}f = id n where{5} n = 2 m = 3{0} ␣␣f = id 2 ␣␣{3}f = id 2{0} f = id n where <tab>n = 2 {1}f = id n where{16} <tab>n = 2{0}
  10. <n> τʔΫϯ • Rule • ߦ಄͔Β whitespace ͕ଓ͘ lexeme ͷ৔߹

    <n> Λ lexeme ͷલʹૠೖ͢Δ • n ͸ lexeme ͷΠϯσϯτྔ • ෳ਺ߦ͔ΒͳΔจࣈྻϦςϥϧͷखલʹ͸ૠೖ͠ͳ͍
  11. f = id 2 {1}f = id 2{0} f =

    id n where n = 2 {1}f = id n <3>where{9} n = 2{0} f = id n where n = 2 m = 3 {1}f = id n <3>where{5} <5>n = 2 <5>m = 3{0} ␣␣f = id 2 ␣␣{3}f = id 2{0}
  12. Stack of layout contexts Stack ͷཁૉ ҙຯ 0 ɾϨΠΞ΢τ͕໌ࣔతʹࢦఆ͞Ε͍ͯΔɻ (ϓϩάϥϚ͕

    {;} Λ࢖ͬͯίʔυΛॻ͍͍ͯΔ৔߹) ɾϑΝΠϧͷऴ୺ ਖ਼ͷ੔਺ ϒϩοΫͷΠϯσϯτྔ
  13. L (part 0) • L ؔ਺͸ laidout ϓϩάϥϜͷग़ྗΛೖྗͱͯ͠औΓɺϨ ΠΞ΢τʹґଘ͠ͳ͍ϓϩάϥϜΛੜ੒͢Δ •

    L tokens [ ] ͱͯ͠ݺͼग़͢ • ελοΫͷ௕͞ = ݱࡏͷϨΠΞ΢τͷωετͷਂ͞
  14. L (part 1) ։࢝ॲཧ layout  [Token]  LayoutContext 

    [Token] layout (IndentBrace n:ts) [] | n > 0 = Lexeme "{" : layout ts [n] -- (1) Ұ൪֎ଆͷϨΠΞ΢τϒϩοΫ layout (IndentBrace n:ts) (m:ms) | n > m = Lexeme "{" : layout ts (n:m:ms) -- (2) 2ͭ໨Ҏ߱ͷϨΠΞ΢τϒϩοΫ layout (IndentBrace n:ts) ms = Lexeme "{" : Lexeme "}" : layout (IndentLine n:ts) ms -- (3) ۭ where ͳͲ data Token = Lexeme String | Space | Tab | Newline | IndentBrace Int -- ^ {n} | IndentLine Int -- ^ <n> deriving (Eq, Show)
  15. • (1) Ұ൪֎ଆͷϨΠΞ΢τϒϩοΫ • n > 0 ͸ϑΝΠϧͷऴ୺͔Ͳ͏͔ͷνΣοΫ • (2)

    2ͭ໨Ҏ߱ͷϨΠΞ΢τϒϩοΫ • n > m ͸࣍ͷϨΠΞ΢τϒϩοΫͷΠϯσϯτྔ͸ɺલ ͷϨΠΞ΢τϒϩοΫΑΓ΋େ͖͘ͳ͚Ε͹ͳΒͳ͍ ͱ͍͏੍໿ • ৽͍͠ϒϩοΫ͕࢝·ΔͷͰελοΫ͸ n ͕1ͭ૿͑Δ {1}f = id n <3>where{5} <5>n = 2 where{7} <7>m = 3{0}
  16. • (3) ۭͷ where ౳ • ͜ͷߦʹ౸ୡ͢Δͷ͸ 0 < n

    <= m ͷͱ͖ • {} ͕ૠೖ͞Εɺଓ͘ߦ͸ಉ͡ϨΠΞ΢τϒϩοΫͱͯ͠ ղऍ͞ΕΔ {1}f = id n <3>where{5} <5>n = 2 where{5} <5>m = 3{0}
  17. L (part 2) ߦॲཧ layout  [Token]  LayoutContext 

    [Token] layout tokens@(IndentLine n:ts) (m:ms) | m  n = Lexeme ";" : layout ts (m:ms) -- (4) ಉ͡ϨΠΞ΢τϒϩοΫͱͯ͠ߦΛॲཧ͢Δ | n < m = Lexeme "}" : layout tokens ms -- (5) ϨΠΞ΢τϒϩοΫͷऴྃ layout (IndentLine n:ts) ms = layout ts ms -- (6) લͷߦ͔Βଓ͘ॲཧ data Token = Lexeme String | Space | Tab | Newline | IndentBrace Int -- ^ {n} | IndentLine Int -- ^ <n> deriving (Eq, Show)
  18. • (4) ಉ͡ϨΠΞ΢τϒϩοΫͱͯ͠ߦΛॲཧ͢Δ • m == n ͰݱࡏͷϨΠΞ΢τϒϩοΫͷਂ͞ͱɺlexeme ͷΠϯσϯ τྔ͕Ϛον͍ͯ͠Δ͔νΣοΫ

    • (5) ϨΠΞ΢τϒϩοΫͷऴྃ • ϑΝΠϧͷऴ୺ {0} ΋͜͜Ͱ൑ఆͰ͖Δ • τʔΫϯ͸ফඅ͠ͳ͍͕ɺελοΫ͸1ͭݮΔ • (6) લͷߦ͔Βଓ͘ॲཧ • n > m ͷͱ͖ {1}f = id n <3>where{5} <5>n = 2 + 3{0}
  19. L (part 3) ໌ࣔతͳࢦఆ layout  [Token]  LayoutContext 

    [Token] layout (Lexeme "{":ts) ms = Lexeme "{" : layout ts (0:ms) -- (7) ϓϩάϥϚʹΑΔ໌ࣔతͳ։࢝ॲཧ layout (Lexeme "}":ts) (0:ms) = Lexeme "}" : layout ts ms -- (8) ϓϩάϥϚʹΑΔ໌ࣔతͳऴྃॲཧ layout (Lexeme "}":ts) ms = error “parse-error" -- (9) ׅހͷରԠ͕औΕ͍ͯͳ͍৔߹ͷΤϥʔॲཧ data Token = Lexeme String | Space | Tab | Newline | IndentBrace Int -- ^ {n} | IndentLine Int -- ^ <n> deriving (Eq, Show)
  20. • (7) ϓϩάϥϚʹΑΔ໌ࣔతͳ։࢝ॲཧ • ελοΫʹ͸ 0 ͕ੵ·ΕΔɻ͜Ε͸ɺϓϩάϥϚ͕໌ ࣔతʹ ; Λૠೖ͢ΔͨΊΠϯσϯτྔͷ؅ཧΛ͠ͳ͍ͱ

    ͍͏ϑϥά • (8) ϓϩάϥϚʹΑΔ໌ࣔతͳऴྃॲཧ • (9) ׅހͷରԠ͕औΕ͍ͯͳ͍৔߹ͷΤϥʔॲཧ • Ϩίʔυߏจ΋ (7) ~ (9) Ͱॲཧ͞ΕΔ
  21. L (part 4) τʔΫϯͷॲཧ layout  [Token]  LayoutContext 

    [Token] layout (t:ts) (m:ms) | m  0 && pe t = Lexeme "}" : layout (t:ts) ms -- (10) parse error ࣌͸ϒϩοΫͷऴྃͱΈͳ͢ where pe _ = False -- FIXME layout(t:ts) ms = t : layout ts ms -- (11) τʔΫϯͷૠೖ data Token = Lexeme String | Space | Tab | Newline | IndentBrace Int -- ^ {n} | IndentLine Int -- ^ <n> deriving (Eq, Show)
  22. • (10) parse error ࣌͸ϒϩοΫͷऴྃͱΈͳ͢ • Parser ͰΤϥʔ͕ى͖ͨΒ } Λૠೖ͢Δ

    • ͜ͷϧʔϧ͕͋ΔͨΊ Laxer & Parser Ͱ৘ใΛڞ༗͢ Δඞཁ͕͋Δ • (11) τʔΫϯͷૠೖ • ϓϩάϥϚʹΑΔ ; ͷࢦఆ΋͜͜ʹؚ·ΕΔ let x = do f; g in x
  23. L (part 5) ऴྃॲཧ layout  [Token]  LayoutContext 

    [Token] layout [] [] = [] -- (12) ࣗ໌ͳجఈ෦ layout [] (m:ms) | m  0 = Lexeme "}" : layout [] ms -- (13) ϒϩοΫͷऴྃॲཧ data Token = Lexeme String | Space | Tab | Newline | IndentBrace Int -- ^ {n} | IndentLine Int -- ^ <n> deriving (Eq, Show)
  24. ·ͱΊ • Laidout ؔ਺ͱ L ؔ਺Λ্ख͘·ͱΊͯ parser-combinator Ͱॲཧ͢Δ͜ͱ͸Մೳ (ࢀߟϦιʔε[3]) •

    indentation package • Laidout ؔ਺Ͱඞཁͳ৘ใ • ࠷ॳͷ Lexeme ͔Ͳ͏͔൑ఆ͢ΔͨΊͷ Bool ஋ • ߦ಄͔Βεϖʔε͕ଓ͍͍ͯΔ͔൑ఆ͢ΔͨΊͷ Bool ஋ • ݱࡏॲཧ͍ͯ͠ΔΧϥϜ൪߸Λද͢ Int ஋ • L ؔ਺Ͱඞཁͳ৘ใ • LayoutContext ελοΫ (ܕ͸ [Int] ͱ͔) • ύʔζ͕੒ޭ͔ͨ͠Ͳ͏͔
  25. ࢀߟϦιʔε 1. Haskell Language Report 98 2. Haskell2010 Language Report

    ೔ຊޠ༁ (myuon/ haskell2010-ja) 3. Indentation-Sensitive Parsing for Parsec