为简单起见,我们假设我的 HList
实例恰好包含 2 个值:
def intToString(x: Int) = x + "_"
def intToDouble(x: Int) = x * 10d
val fns = (intToString _ :: intToDouble _ :: HNil)
现在我想,有一些 Hlist
的整数,能够做到这一点:
(fns zip (1 :: 2 :: HList) map {case (f, x) => f(x) }
得到
("1_", 10.0)
从现在开始,假设我不知道自己在做什么,我完全理解我在功能性神灵面前的所有卑鄙。
我已经看过 shapeless 的 wiki,据我所知,我应该制作一个从 Int
到 T
的函数,它可以被 shapeless 接受。我理解正确吗?这是我得到的:
object mapApply extends Poly1 {
implicit def default[T] = at[Function[Int,T]](f => f.apply _)
}
此时我完全迷失了方向,甚至不知道如何继续。但我有点着迷于它可以提供的潜在力量和表现力,所以我真的很想了解这些东西是如何工作的。如果您的回答不仅仅是代码片段,而是更加开放和解释性的,我将不胜感激。
附言SO 的引擎刚刚向我建议了一个 c++
标签。我是不是说了一些类似 C++ 的东西?
最佳答案
看起来您在混合使用方法和函数定义语法——我假设您的意思如下:
val intToString = (x: Int) => x + "_"
val intToDouble = (x: Int) => x * 10d
val fns = intToString :: intToDouble :: HNil
现在您可以使用 zipApply
,它只是将函数及其参数配对:
val res = fns.zipApply(1 :: 2 :: HNil)
如果由于某种原因 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)
或者这个,如果你不想要额外的通用性:
object applyToInt extends Poly1 {
implicit def default[T]: Case.Aux[(Int => T, Int), T] =
at[(Int => T, Int)] { case (f, x) => f(x) }
}
所以您离得并不远——您只需要在 Poly1
中为函数和参数的对设置一个 case,而不仅仅是函数.
关于scala - 如何将函数映射到函数的 HList 从某种类型到某种类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24685499/