`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
次(List
s 大小),并将其“修复”为输入。
In my view, I am essentially asking the compiler to "duplicate" that input A
some n
times (the List
s 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]]
nest
和 explode
让人联想到 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)
}
我正在尝试为这个 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
次(List
s 大小),并将其“修复”为输入。
In my view, I am essentially asking the compiler to "duplicate" that input
A
somen
times (theList
s 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]]
nest
和 explode
让人联想到 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)
}