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

标签 scala functional-programming shapeless

为简单起见,我们假设我的 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,据我所知,我应该制作一个从 IntT 的函数,它可以被 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/

相关文章:

scala - 使用单例类型理解 `apply` 和 `unapply`

scala - 异构树的类型级展平

scala - 避免丢失返回值中的类型信息

scala - 如何一次到 "find"序列元素和谓词结果?

scala - 如何在图中找到每个顶点的度-RDD转换?

javascript - 箭头函数中多个表达式不带花括号的做法是什么

javascript - 如何在 Javascript 中实现 Haskell 的 FRP Behavior 类型?

scala - 在 http4s 版本 19.0.0 中找不到 ContextShift[cats.effect.IO] 的隐式值

scala - Scala 的路径依赖类型是什么意思?

F# 将函数应用于它的结果 n 次