简体   繁体   English

如何将函数的HList函数从某种类型映射到某种类型?

[英]How to map a function over the HList of functions from a certain type to some type?

For simplicity sake let's assume my HList instance holds exactly 2 values: 为简单起见,我们假设我的HList实例恰好包含2个值:

def intToString(x: Int) = x + "_"
def intToDouble(x: Int) = x * 10d
val fns = (intToString _ :: intToDouble _ :: HNil)

Now I'd like, having some Hlist of ints, to be able to do this: 现在,我希望能够做到这一点,获得一些内容Hlist

(fns zip (1 :: 2 :: HList) map {case (f, x) => f(x) }

to get 要得到

("1_", 10.0)

From now on, assume that I don't know what I am doing and I totally understand all my paltriness in the faces of the functional gods. 从现在开始,假设我不知道自己在做什么,而且我完全理解功能之神面孔中的所有瑕疵。

I already looked at shapeless' wiki and, as far as I understood, I should make a function from Int to T that can be accepted by shapeless. 我已经看过没有形状的'wiki,据我所知,我应该从IntT创建一个可以被无形接受的函数。 Did I understood correct? 我明白了吗? Here's what I got: 这是我得到的:

object mapApply extends Poly1 {
  implicit def default[T] = at[Function[Int,T]](f => f.apply _)
}

At this point I'm completely lost and don't even have a clue of how to proceed. 在这一点上,我完全迷失了,甚至不知道如何继续。 But I'm kinda fascinated by the potential power and expressiveness that this could deliver, so I'd really like to understand how this stuff works. 但我对这可能带来的潜在力量和表现力有点着迷,所以我真的很想了解这些东西是如何运作的。 I would really appreciate if your answers will not be just code snippets but rather more open and explanatory. 如果您的答案不仅仅是代码片段而是更开放和更具说明性,我将非常感激。

PS SO's engine just suggested me a c++ tag. PS SO的引擎只是建议我一个c++标签。 Did I say something C++-ish? 我说了一些C ++ - 是吗?

It looks like you're mixing method and function definition syntax—I'll assume you meant something like the following: 看起来你正在混合方法和函数定义语法 - 我假设你的意思如下:

val intToString = (x: Int) => x + "_"
val intToDouble = (x: Int) => x * 10d
val fns = intToString :: intToDouble :: HNil

Now you can use zipApply , which just pairs functions and their arguments: 现在你可以使用zipApply ,它只是将函数和它们的参数配对:

val res = fns.zipApply(1 :: 2 :: HNil)

If for some reason zipApply didn't exist, you could accomplish the same thing with a Poly1 : 如果由于某种原因, zipApply不存在,你可以使用Poly1完成同样的事情:

object apply extends Poly1 {
  implicit def default[I, O]: Case.Aux[(I => O, I), O] =
    at[(I => O, I)] { case (f, x) => f(x) }
}

val res = fns.zip(1 :: 2 :: HNil).map(apply)

Or this, if you don't want the extra genericity: 或者,如果你不想要额外的通用性:

object applyToInt extends Poly1 {
  implicit def default[T]: Case.Aux[(Int => T, Int), T] =
    at[(Int => T, Int)] { case (f, x) => f(x) }
}

So you weren't too far off—you just needed to have a case in your Poly1 for the pair of the function and the argument, not just the function. 所以你离得太远 - 你只需要在你的Poly1有一个用于函数和参数的案例,而不仅仅是函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM