`A => List[B]` 可以转换为 `List[A => B]` 吗?

Can `A => List[B]` be transformed into a `List[A => B]`?

我正在尝试为这个 Scala 函数签名找到一个实现:

def explode[A, B](f: A => List[B]): List[A => B]

相反的方向是可能的:

def nest[A, B](fs: List[A => B]): A => List[B] = (a: A) => fs.map(_(a))

现在我倾向于相信第一个 (explode) 是无法实现的,但我很高兴被证明是错误的。如果确实无法实施,背后是否有深层次的道理?

在我看来,我实际上是在要求编译器“复制”输入 A 一些 n 次(Lists 大小),并将其“修复”为输入。

In my view, I am essentially asking the compiler to "duplicate" that input A some n times (the Lists size), and "fix" it as input.

问题是您不知道 n 是什么。例如,考虑一个函数,它 return 是一个数的所有质因数的列表:

def divisors(n: Int): List[Int] = ???

您期望 explode(divisors) 是什么? divisors 可以 return 任何大小的 List,这取决于它的参数,无论何时在将来被调用。但是当你调用 explode 时,它必须立即 return 一个固定大小的 List

给定一个固定类型A,你代码中的签名可以这样写:

type F[T] = List[T]
type G[T] = A => T

def nest[B]: F[G[B]] => G[F[B]]
def explode[B]: G[F[B]] => F[G[B]]

nestexplode 让人联想到 sequence operation. It works for nest, because it's possible to write a Traverse instance for a List, but it's not possible to write a Traverse instance for a function A => T. Here is an equivallent ,这提供了更多见解。

如果你想做一些只满足签名的实现,你可以这样做:

def explode[A, B](f: A => List[B]): List[A => B] = {
  Nil
}

def explode[A, B](f: A => List[B]): List[A => B] = {
  List(f.andThen(_.head))
}

但我猜你想要语义上不同的东西:

"duplicate" that input A some n times (the Lists size), and "fix" it as input

那样的话,就有问题了。在一般情况下,f 的结果取决于输入 A。它可以是 Nil、有限大小列表或无限列表。

你能做的只有:

def explode[A, B](f: A => List[B]): A => List[A => B] = {
  f.andThen(_.map(b => (_: A) => b)
}