(同步发布至Reddit)Elm中如何将定长列表转同长元组?能否用Applicative?
用Applicative风格解决固定长度列表转元组的问题
好问题!其实在Elm里,你完全可以借助Applicative特性来实现这个需求,而且比你当前的case匹配写法更简洁、更安全,还能避免手动处理列表长度不匹配的麻烦。
先说说你现有写法的小问题
你现在的思路是先生成对应长度的种子列表,再通过case模式匹配转成元组。但这种方式有个明显的缺点:每次需要增加或减少种子数量时,你不仅要修改R.list的参数,还要同步修改case里的列表模式和默认元组的元素数量,很容易因为疏忽导致错误。
用Applicative的mapN函数直接生成元组
Elm的Random.Pcg.Generator实现了Applicative接口,官方提供了map2到map8这些函数(因为Elm的元组最多支持8个元素),可以直接把多个独立的Generator组合成一个生成对应长度元组的Generator。
针对你的场景,生成3个种子的代码可以改成这样:
import Random.Pcg as R let ( (seed1, seed2, seed3), newSeed ) = R.step (R.map3 (,,) R.independentSeed R.independentSeed R.independentSeed) seed in -- 这里直接使用seed1、seed2、seed3即可
如果需要第四个种子,只需要改成map4和对应的四元组构造函数(,,,):
let ( (seed1, seed2, seed3, seed4), newSeed ) = R.step (R.map4 (,,,) R.independentSeed R.independentSeed R.independentSeed R.independentSeed) seed in -- 使用四个种子
为什么这种写法更好?
- 更简洁:不需要先生成列表再手动转元组,一步到位生成你需要的元组结构。
- 更安全:
mapN函数会严格保证生成的元组长度和你传入的Generator数量一致,完全避免了列表长度不匹配的情况(也就不需要写那个冗余的默认分支了)。 - 更符合函数式风格:利用Applicative的组合特性,把多个独立的生成逻辑优雅地组合在一起,代码可读性更高。
补充说明
如果你需要生成超过8个元素的元组,那可能得回到列表的方式,但Elm本身不支持更长的元组,这种场景下列表反而更合适。不过一般来说,8个以内的场景用mapN完全足够。
内容的提问来源于stack exchange,提问作者Ralph
相关产品推荐
相关产品推荐

