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

LayoutRule in Haskell (98)

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for wado wado
March 18, 2019

LayoutRule in Haskell (98)

Avatar for wado

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