Mapping over Shapeless record

前端 未结 1 730
执笔经年
执笔经年 2021-01-02 02:07

In a Play application I\'m working on, I\'m trying to improve our system for processing flags, some of which are meant to be persistent options as a user navigates our app v

1条回答
  •  一生所求
    2021-01-02 02:48

    Update: the FieldPoly helper actually doesn't do all that much work for you here, and you can accomplish the same thing without it (and without the Witness implicit):

    import shapeless.labelled.{ FieldType, field }
    
    object bind extends Poly1 {
      implicit def rpb[T, K]: Case.Aux[
        FieldType[K, RequestParamBuilder[T]],
        FieldType[K, RequestParam[T]]
      ] = at[FieldType[K, RequestParamBuilder[T]]](b => field[K](b(requestParams)))
    }
    

    It's also worth noting that if you don't mind living dangerously, you can skip the return type (in both implementations):

    object bind extends Poly1 {
      implicit def rpb[T, K] = at[FieldType[K, RequestParamBuilder[T]]](b =>
        field[K](b(requestParams))
      )
    }
    

    But in general having an implicit method with an inferred return type is a bad idea.


    As I mention in a comment above, Case isn't covariant, which means that your bind will only work if the elements of the HList are statically typed as RequestParamBuilder (in which case you don't have a record).

    You could use .values to get the values out of the record, and you can then map over the result, but (as you note) this would mean you lose the keys. If you want to preserve the keys, you can use Shapeless's FieldPoly, which is designed to help out in this kind of situation:

    import shapeless.labelled.FieldPoly
    
    object bind extends FieldPoly {
      implicit def rpb[T, K](implicit witness: Witness.Aux[K]): Case.Aux[
        FieldType[K, RequestParamBuilder[T]],
        FieldType[K, RequestParam[T]]
      ] = atField(witness)(_(requestParams))
    }
    

    Now options.map(bind) will work as expected.

    I don't think there's a better way to write this at the moment, but I haven't been following the most recent Shapeless developments very closely. In any case this is reasonably clear, not too verbose, and it does what you want.

    To answer the other question in your comment: this previous question is a starting point, but I'm not aware of a really good overview of the mechanics of the implementation of polymorphic function values in Shapeless. It's a good idea for a blog post.

    0 讨论(0)
提交回复
热议问题