{"record":{"id":"b1143b2ccd6d7472","repo":"xai-org/x-algorithm","slug":"function-passed-to-foldl-returns-s-but-seed-val","errorCode":null,"errorMessage":"function passed to Foldl() returns %s but seed value is a %s","messagePattern":"function passed to Foldl\\(\\) returns (.+?) but seed value is a (.+?)","errorType":"validation","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/compiler/Compiler.java","lineNumber":931,"sourceCode":"    Type fromType = Type.OBJECT;\n    if (Collection.class.isAssignableFrom(collectionNode.getReturnType().typeBase)) {\n      fromType = collectionNode.getReturnType().getTypeParams().get(0);\n    }\n    Type seedType = seedValueNode.getReturnType();\n\n    CompilerScope scope = context.addScope();\n    long scopeId = context.currentScopeId();\n    Parameter parameterA = Parameter.scope(\n        varA, seedType, scopeId, seedValueNode);\n    scope.defineVariable(parameterA);\n\n    Parameter parameterB = Parameter.scope(\n        varB, fromType, scopeId, collectionNode);\n    scope.defineVariable(parameterB);\n\n    ASTNode funcNode = createASTNodeTree(context, funcTree);\n    if (Type.isDivergentTo(funcNode.getReturnType(), seedType)) {\n      throw new SemanticCheckFailure(\n          String.format(\n              \"function passed to Foldl() returns %s but seed value is a %s\",\n              funcNode.getReturnType(),\n              seedType));\n    }\n\n    context.removeScope();\n\n    ASTNode result = Fold.createFoldl(exprText, varA, varB, funcNode, seedValueNode,\n        context.currentScopeId(), collectionNode);\n    return result;\n  }\n\n  private ASTNode toFoldl1(CompilerContext context, String exprText, Tree root)\n      throws ParseFailure, SemanticCheckFailure {\n    String varA = getVariableName(root.getChild(1));\n    String varB = getVariableName(root.getChild(2));\n    ASTNode collectionNode = createASTNodeTree(context, root.getChild(4));","sourceCodeStart":913,"sourceCodeEnd":949,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/compiler/Compiler.java#L913-L949","documentation":"Foldl (left fold) requires the folding function's return type to be compatible with the seed value's type. If the function diverges from the seed type, the accumulator type would change across iterations, which the statically typed DSL forbids.","triggerScenarios":"`Foldl(collection, seed, fn)` where fn returns e.g. Double while seed is a Long, or fn returns a struct while the seed is a primitive.","commonSituations":"Writing a fold that accumulates a different type than it takes (e.g. summing into a string, or building a list from an int seed), or assuming implicit numeric coercion that Botmaker does not perform.","solutions":["Make the seed's type match the function's return type","Rewrite the folding function so it returns the same type as its seed argument","If changing types mid-fold is needed, do the conversion in an outer expression instead"],"exampleFix":"// before\nFoldl(nums, 0L, (acc, x) -> ToDouble(acc + x))\n// after\nFoldl(nums, 0L, (acc, x) -> acc + x)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// in DSL: ensure fold fn return type == seed type before compiling\nif (!fnReturnType.equals(seedType)) throw new IllegalArgumentException(\"Foldl seed/fn type mismatch\");","tryCatchPattern":"catch (SemanticCheckFailure e) { if (e.getMessage().contains(\"Foldl\")) surfaceTypeHint(e); else throw e; }","preventionTips":["Always start Foldl with a seed of the accumulator type you want","Keep fold lambdas type-stable"],"tags":["botmaker","foldl","type-mismatch"],"backgroundTag":"fold-type-mismatch","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}