Using Cont to acquire values from the future and the past

后端 未结 2 1229
自闭症患者
自闭症患者 2021-02-02 13:02

I\'m writing a brainfuck interpreter in Haskell, and I came up with what I believe to be a very interesting description of a program:

data Program m = Instructio         


        
2条回答
  •  南方客
    南方客 (楼主)
    2021-02-02 13:29

    Forwards traveling state with a continuation monad looks like this:

    Cont (fw -> r) a
    

    Then the type of the argument to cont is

    (a -> fw -> r) -> fw -> r
    

    So you get a fw passed in from the past which you have to pass on to the continuation.

    Backwards traveling state looks like this:

    Cont (bw, r) a
    

    Then the type of the argument to cont is

    (a -> (bw, r)) -> (bw, r)
    

    I.e. you get a bw from the continuation which you have to pass on to the past.

    These can be combined into one continuation monad:

    Cont (fw -> (bw, r)) a
    

    There's a catch when applying this to your parser, because toProgramStep builds the program in reverse, so the list of ']' points is the forward state, and the list of '[' points is the backward state. Also, I got lazy and skipped the Maybe part, which should catch the pattern matching errors in openBrace and closeBrace.

    type ParseState = Cont ([TapeP] -> ([TapeP], TapeP))
    
    toProgram :: String -> TapeP
    toProgram = snd . ($ []) . (`runCont` (\a _ -> ([], a))) . toProgramStep
    
    
    openBrace :: ParseState TapeP -> ParseState TapeP
    openBrace mcontinue = do
      continue <- mcontinue
      cont $ \k (break:bs) -> let (cs, r) = k (loopControl continue break) bs in (continue:cs, r)
    
    closeBrace :: ParseState TapeP -> ParseState TapeP
    closeBrace mbreak = do
      break <- mbreak
      cont $ \k bs -> let (continue:cs, r) = k (loopControl continue break) (break:bs) in (cs, r)
    

提交回复
热议问题