Lazify状态机

发布于 2025-01-29 11:58:16 字数 1260 浏览 2 评论 0原文

我是Haskell的初学者,我正在尝试写一台懒惰的Lexer状态机。

我有这个代码,确定不是懒惰的代码。因此,我应该用什么样的库或模式来懒惰的此代码?

module Main where

import           Control.Monad.State.Lazy
import           Data.Sequence (Seq (..))
import qualified Data.Sequence as Seq

data Suppe = A | B Integer

data StateBase = StateBase String (Seq Suppe)

newtype StateFn = StateFn (StateBase -> (Maybe StateFn, StateBase))

type StateMachine = (Maybe StateFn, StateBase)

next :: StateMachine -> StateMachine
next (Just (StateFn f), x) = f x
next (Nothing, x) = (Nothing, x)

run :: String -> Seq Lexeme
run input = evalState go (Just startStateFn, startState) 
  where
    startState = StateBase input Seq.empty
    startStateFn = FnA

    go :: State StateMachine (Seq Lexeme)
    go = get >>= \stateMachine -> let newStateMachine = next stateMachine
      in
      case fst newStateMachine of
        (Just _) -> put newStateMachine >> go
        Nothing -> return $ getSeq $ snd newStateMachine
    getSeq :: StateBase -> Seq Suppe
    getSeq (StateBase _ seq) = seq

fnA :: StateFn
fnA = undefined

fnB :: StateFn
fnB = undefined

main = undefined

我正在使用容器 ^> = 0.6.0.1,mtl ^> = 2.2

I am beginner to Haskell and I am trying to write a Lexer State Machine that is Lazy.

I have this code that definitive is no lazy code. Thus what kind of library or pattern should I use to lazy-fy this code?

module Main where

import           Control.Monad.State.Lazy
import           Data.Sequence (Seq (..))
import qualified Data.Sequence as Seq

data Suppe = A | B Integer

data StateBase = StateBase String (Seq Suppe)

newtype StateFn = StateFn (StateBase -> (Maybe StateFn, StateBase))

type StateMachine = (Maybe StateFn, StateBase)

next :: StateMachine -> StateMachine
next (Just (StateFn f), x) = f x
next (Nothing, x) = (Nothing, x)

run :: String -> Seq Lexeme
run input = evalState go (Just startStateFn, startState) 
  where
    startState = StateBase input Seq.empty
    startStateFn = FnA

    go :: State StateMachine (Seq Lexeme)
    go = get >>= \stateMachine -> let newStateMachine = next stateMachine
      in
      case fst newStateMachine of
        (Just _) -> put newStateMachine >> go
        Nothing -> return $ getSeq $ snd newStateMachine
    getSeq :: StateBase -> Seq Suppe
    getSeq (StateBase _ seq) = seq

fnA :: StateFn
fnA = undefined

fnB :: StateFn
fnB = undefined

main = undefined

I am using containers ^>= 0.6.0.1, mtl ^>= 2.2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

世界如花海般美丽 2025-02-05 11:58:16

对我来说,看来您周围有太多的机器,这只是使事情混乱,使它难以看到懒惰在哪里丢失。您是否尝试过仅使用Direct Style编程?这样的事情:

import Data.Char

data Lexeme = A | B Integer

stateAOrB :: String -> [Lexeme]
stateAOrB ('A':rest) = stateA rest
stateAOrB ('B':rest) = stateB 0 rest
stateAOrB (_:rest) = error "lex error" -- or, could return [Maybe Lexeme] or [Either PositionInformation Lexeme] or whatever
stateAOrB [] = []

stateA :: String -> [Lexeme]
stateA cs = A : stateAOrB cs

stateB :: Integer -> String -> [Lexeme]
stateB n (c:cs) | isDigit c = stateB (10*n + toInteger (digitToInt c)) cs
stateB n other = B n : stateAOrB other

我猜想这比fnafnb在您的设置中的实现要短(或仅可忽略的),同时清晰且非常明显地懒惰。

To me, it looks like you have way too much machinery lying around, and it's just cluttering things up and making it too hard to see where laziness is being lost. Have you tried just using direct-style programming? Something like this:

import Data.Char

data Lexeme = A | B Integer

stateAOrB :: String -> [Lexeme]
stateAOrB ('A':rest) = stateA rest
stateAOrB ('B':rest) = stateB 0 rest
stateAOrB (_:rest) = error "lex error" -- or, could return [Maybe Lexeme] or [Either PositionInformation Lexeme] or whatever
stateAOrB [] = []

stateA :: String -> [Lexeme]
stateA cs = A : stateAOrB cs

stateB :: Integer -> String -> [Lexeme]
stateB n (c:cs) | isDigit c = stateB (10*n + toInteger (digitToInt c)) cs
stateB n other = B n : stateAOrB other

I would guess this is shorter (or only negligibly longer) than implementations of fnA and fnB in your setting, while being clear and quite visibly lazy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文