Rails/Ruby中dry-monads调用FakeStoreApi时提示无法遍历无类型列表
解决dry-monads中"Cannot traverse an untyped list"错误
你在测试Shftcos API样板代码时,用到了不熟悉的dry-monads gem,调用FakeStoreApi获取产品的服务请求触发了如下错误:
Cannot traverse an untyped list (StandardError)
对应的服务代码如下:
require 'faraday' require 'json' class FetchProductsService < ApplicationService def call result = yield fetch_products Success(result) end private def fetch_products products = [] response = Faraday.get('https://fakestoreapi.com/products') if response.status == 200 products = JSON.parse(response.body) end products end end
问题原因
dry-monads的traverse操作(处理集合类型Monad时常用)要求集合是有明确类型的容器,而你当前fetch_products返回的是原生Ruby数组(Array),属于无类型列表,dry-monads无法识别它来执行traverse操作。
解决方法
1. 用dry-monads的List类型包装返回数组
dry-monads提供了Dry::Monads::List来作为有类型的集合容器,修改代码如下:
require 'faraday' require 'json' require 'dry/monads/list' class FetchProductsService < ApplicationService include Dry::Monads::List::Mixin def call result = yield fetch_products Success(result) end private def fetch_products products = [] response = Faraday.get('https://fakestoreapi.com/products') if response.status == 200 products = JSON.parse(response.body) end List(products) # 将普通数组转换为dry-monads的List类型 end end
2. 检查上层调用逻辑
如果是上层代码在处理FetchProductsService.call的结果时执行了traverse,也可以在那里把原生数组转为List,但更推荐在服务内部统一返回有类型容器,保证代码风格一致。
补充说明
dry-monads的设计核心就是通过有类型容器明确数据结构,避免无类型集合的不确定性,所以涉及Monad的集合操作时,必须使用它提供的List(或其他兼容有类型集合),而非原生Ruby数组。
内容的提问来源于stack exchange,提问作者Paul Anthony McGowan
相关产品推荐
相关产品推荐

