如何修正Haskell蛋糕烘焙状态机的语法错误与逻辑问题?
蛋糕烘焙状态机Haskell实现修正问题
需求说明
已定义如下Haskell类型:
data Event = AddEggs | AddFlour | AddSugar | Mix | Bake deriving (Eq, Show)
data State = Start | Error | Finished | HasEggs | HasFlour | HasSugar | HasFlourAndSugar | Mixed deriving (Eq, Show)
状态机规则:
- 初始状态为
Start,终止状态为Error或Finished - 合法事件序列:
[AddEggs, AddFlour, AddSugar, Mix, Bake][AddEggs, AddSugar, AddFlour, Mix, Bake]
AddFlour与AddSugar顺序可互换- 进入
Error或Finished后状态不再变更 - 任何违规操作直接进入
Error且无法恢复
原始实现代码
data Event = AddEggs | AddFlour | AddSugar | Mix | Bake deriving (Eq, Show) data State = Start | Error | Finished | HasEggs | HasFlour | HasSugar | HasFlourAndSugar | Mixed deriving (Eq, Show) stepHelper :: State -> Event -> Bool -> Bool -> State stepHelper Start AddEggs False False = HasEggs stepHelper Start AddEggs True _ = Error stepHelper Start AddEggs _ True = Error stepHelper Start _ _ _ = Error stepHelper HasEggs AddFlour has_flour has_sugar = if has_flour then Error else HasFlour stepHelper HasEggs AddSugar has_flour has_sugar = if has_sugar then Error else HasSugar stepHelper HasEggs AddFlour _ has_sugar = stepHelper HasEggs AddFlour True has_sugar stepHelper HasEggs AddSugar has_flour _ = stepHelper HasEggs AddSugar has_flour True stepHelper _ Mix has_flour has_sugar = if has_flour && has_sugar then Mixed else Error stepHelper Mixed Bake _ _ = Finished step :: State -> Event -> State step s e = stepHelper s e False False -- do not edit this bake :: [Event] -> State bake events = go Start events where go state [] = state go state (e:es) = go (step state e) es
报错信息
运行stack runhaskell Set7Test.hs后出现:
Set7.hs:61:1: warning: [-Wtabs] Tab character found here, and in 29 further locations. Please use spaces instead. | 61 | ------------------------------------------------------------------------------ | ^^^^^^^^ Set7.hs:119:29: error: parse error on input `=' | 119 | go state (e:es) = go (step state e) es
修正后的代码
data Event = AddEggs | AddFlour | AddSugar | Mix | Bake deriving (Eq, Show) data State = Start | Error | Finished | HasEggs | HasFlour | HasSugar | HasFlourAndSugar | Mixed deriving (Eq, Show) -- 核心状态转换函数,处理单个事件的状态变更 step :: State -> Event -> State -- 终止状态保持不变 step Error _ = Error step Finished _ = Finished -- 初始状态Start的转换 step Start AddEggs = HasEggs step Start _ = Error -- Start状态下只能加鸡蛋,其他操作直接报错 -- HasEggs状态的转换 step HasEggs AddFlour = HasFlour step HasEggs AddSugar = HasSugar step HasEggs _ = Error -- HasEggs状态下只能加面粉或糖,其他操作报错 -- HasFlour状态的转换 step HasFlour AddSugar = HasFlourAndSugar step HasFlour _ = Error -- HasFlour状态下只能加糖,其他操作报错 -- HasSugar状态的转换 step HasSugar AddFlour = HasFlourAndSugar step HasSugar _ = Error -- HasSugar状态下只能加面粉,其他操作报错 -- HasFlourAndSugar状态的转换 step HasFlourAndSugar Mix = Mixed step HasFlourAndSugar _ = Error -- 该状态下只能搅拌,其他操作报错 -- Mixed状态的转换 step Mixed Bake = Finished step Mixed _ = Error -- Mixed状态下只能烘焙,其他操作报错 -- 兜底匹配(理论上不会触发) step _ _ = Error -- 遍历事件序列的函数(保持原代码不变) bake :: [Event] -> State bake events = go Start events where go state [] = state go state (e:es) = go (step state e) es
修正说明
语法错误修复:
- 将所有制表符替换为空格,消除
-Wtabs警告 - 移除冗余的
stepHelper函数,简化逻辑结构,避免参数传递导致的解析错误
- 将所有制表符替换为空格,消除
逻辑错误修复:
- 新增终止状态(
Error/Finished)的固定转换规则,确保进入后状态不再变更 - 完善每个状态的合法事件判断,严格遵循规则:
Start仅接受AddEggsHasEggs仅接受AddFlour或AddSugarHasFlour仅接受AddSugar,转换到HasFlourAndSugarHasSugar仅接受AddFlour,转换到HasFlourAndSugarHasFlourAndSugar仅接受Mix,转换到MixedMixed仅接受Bake,转换到Finished
- 所有非法事件直接触发
Error状态,符合规则要求
- 新增终止状态(
内容的提问来源于stack exchange,提问作者coderodde
相关产品推荐
相关产品推荐

