Elm 0.19.1中使用Json.Decode.andThen解码元组的类型不匹配问题
解决Elm 0.19.1解码器与Cmd元组的类型不匹配问题
问题本质是Elm的Json.Decode.andThen要求传入的函数返回纯Decoder a类型,但你试图在解码器中混合返回解码器和副作用命令(Cmd)——而Decoder设计为纯函数,无法携带副作用,因此必须拆分逻辑。
解决方案:拆分纯解码逻辑与Cmd生成
将解码逻辑和Cmd生成完全分离,先完成纯JSON解码得到Criterion值,再根据该值生成对应的命令列表。
1. 重构纯解码器
修改所有解码器,让它们仅返回纯Decoder Criterion,移除Cmd相关返回值:
import Json.Decode as JD exposing (Decoder, field) type Criterion = Condition Condition | CriterionGroup ConditionGroup -- 假设你已定义的Condition和ConditionGroup类型 type alias Condition = { ... } type alias ConditionGroup = { ... } criteriaDecoder : List Field -> List Operator -> Int -> Decoder Criterion criteriaDecoder fields operators currentDepth = field "type" JD.string |> JD.andThen (criterionDecoder fields operators currentDepth) criterionDecoder : List Field -> List Operator -> Int -> String -> Decoder Criterion criterionDecoder fields operators currentDepth criterionType = case criterionType of "condition" -> JD.map Condition (conditionDecoder fields operators) "conditionGroup" -> JD.map CriterionGroup (groupDecoder fields operators currentDepth) _ -> JD.fail <| "Could not decode criterion for type: " ++ criterionType -- 纯Condition解码器,仅处理JSON解码 conditionDecoder : List Field -> List Operator -> Decoder Condition conditionDecoder fields operators = -- 替换为你原本的Condition解码逻辑(移除Cmd返回) JD.map2 Condition (field "field" JD.string) (field "operator" JD.string) -- 纯ConditionGroup解码器,仅处理JSON解码 groupDecoder : List Field -> List Operator -> Int -> Decoder ConditionGroup groupDecoder fields operators currentDepth = -- 替换为你原本的Group解码逻辑(移除Cmd返回) JD.map2 ConditionGroup (field "operator" JD.string) (field "criteria" (JD.list (criteriaDecoder fields operators (currentDepth + 1))))
2. 单独编写Cmd生成函数
根据解码后的Criterion值,生成对应的命令列表:
getCriteriaCmds : Criterion -> List (Cmd Msg) getCriteriaCmds criterion = case criterion of Condition cond -> -- 生成与Condition对应的Cmd(替换为你的实际逻辑) getConditionCmds cond CriterionGroup group -> -- 生成Group对应的Cmd,并递归处理子Criteria的Cmd getGroupCmds group ++ List.concatMap getCriteriaCmds group.criteria -- 示例:Condition对应的Cmd生成逻辑 getConditionCmds : Condition -> List (Cmd Msg) getConditionCmds cond = [ Cmd.none ] -- 替换为实际需要的命令 -- 示例:ConditionGroup对应的Cmd生成逻辑 getGroupCmds : ConditionGroup -> List (Cmd Msg) getGroupCmds group = [ Cmd.none ] -- 替换为实际需要的命令
3. 使用流程
解码JSON后,再调用Cmd生成函数得到最终结果:
decodeAndProcess : String -> Result String (Criterion, List (Cmd Msg)) decodeAndProcess jsonString = case JD.decodeString (criteriaDecoder fields operators 0) jsonString of Ok criterion -> Ok (criterion, getCriteriaCmds criterion) Err err -> Err (JD.errorToString err)
关键说明
Elm的Decoder是纯函数,仅负责将JSON转换为Elm数据,不能包含副作用逻辑(如Cmd)。将解码和Cmd生成分离,既符合Elm的纯函数设计原则,也解决了类型不匹配的问题。
内容的提问来源于stack exchange,提问作者TBatist
相关产品推荐
相关产品推荐

