构建类tryhaskell/openjscad的Web应用:如何用mueval安全运行含函数定义的不可信Haskell代码?
嘿,这个结合Haskell类型安全和CSG可视化的想法太酷了!关于用mueval运行带函数定义的Haskell代码,我刚好有实践经验可以分享,帮你搞定这个问题。
核心思路:让mueval识别顶层定义
mueval默认确实更偏向执行单表达式,但它完全支持运行包含顶层函数/数据定义的代码——关键是要把定义和最终要评估的表达式打包在一起,或者明确告诉mueval要执行哪个顶层符号。
具体实现步骤
1. 打包用户代码+执行目标
假设用户提交的代码是这样的(包含自定义CSG实体的函数定义):
-- 用户提交的代码 myCustomShape :: Solid myCustomShape = cube 1 1 1 `union` sphere 0.7
服务端需要把它包装成一个完整的代码块,加上必要的导入(比如你实现的CSG模块),然后告诉mueval要评估myCustomShape。命令行示例如下:
mueval --code "module TempCSG where import YourCSG (Solid, cube, sphere, union); myCustomShape = cube 1 1 1 `union` sphere 0.7" --eval "myCustomShape" --timeout 5
--code:传递包含模块声明、导入和用户定义的完整代码--eval:指定最终要执行评估的顶层符号(也就是用户定义的实体)--timeout 5:防止用户代码无限循环,超时5秒自动终止
2. 处理长代码或复杂模块
如果用户提交的是完整的模块(比如包含多个函数定义),你可以直接把整个模块内容塞进--code参数里,只要最后指定要评估的目标表达式就行。比如用户代码:
module UserCSG where import YourCSG baseCube :: Solid baseCube = cube 2 2 0.5 topSphere :: Solid topSphere = translate 0 0 1 (sphere 1) finalShape :: Solid finalShape = baseCube `union` topSphere
对应的mueval命令:
mueval --code "$(cat user-submitted-module.hs)" --eval "finalShape" --timeout 5
3. 结合Web应用的服务端流程
把这个逻辑集成到你的Web服务里,大致流程是:
- 接收前端传来的用户Haskell代码
- 拼接必要的导入语句(确保能访问你的CSG函数)
- 调用mueval命令,捕获输出结果或错误信息
- 将评估后的CSG实体序列化成前端能解析的格式(比如JSON结构,包含顶点、面等数据)
- 返回给前端进行3D渲染
关键注意事项
- 安全沙箱:mueval的沙箱能阻止大部分危险操作,但要确保你的CSG模块没有使用
unsafePerformIO、系统调用这类危险代码,避免沙箱逃逸。 - 错误处理:mueval会返回类型错误、语法错误等信息,服务端可以把这些信息原封不动返回给前端,像tryhaskell.org那样提示用户。
- 模块路径:如果你的CSG模块不在GHC默认搜索路径里,需要用
-i参数指定模块所在目录,比如mueval -i ./your-csg-lib --code ...。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

