是否可以在参数列表上执行foldLeft
,其中提供给fold的初始值是完全curried函数,运算符是apply
,列表是要传递给函数f
的参数列表?在Scala中使用foldLeft对curried函数应用参数列表
例如,假设f定义为:
scala> val f = (i: Int, j: Int, k: Int, l: Int) => i+j+k+l
f: (Int, Int, Int, Int) => Int = <function4>
对此我们当然可以直接使用:
scala> f(1, 2, 3, 4)
res1: Int = 10
或者咖喱和应用的参数每次一个:
scala> f.curried
res2: Int => Int => Int => Int => Int = <function1>
scala> f.curried.apply(1).apply(2).apply(3).apply(4)
res3: Int = 10
乍一看,这看起来像一个foldLeft
的工作。
我在使用foldLeft
描述的apply
此序列第一次尝试看起来像:
scala> List(1, 2, 3, 4).foldLeft(f.curried)({ (g, x) => g.apply(x) })
然而,产生以下错误:
<console>:9: error: type mismatch;
found : Int => Int => Int => Int
required: Int => Int => Int => Int => Int
List(1, 2, 3, 4).foldLeft(f.curried)({ (g, x) => g.apply(x) })
我的错误消息的读数是类型推断将需要一些暗示g
。
我在寻找解决办法离开我的一切原始表达式未修改除外g
类型:
List(1, 2, 3, 4).foldLeft(f.curried)({ (g: ANSWER, x) => g.apply(x) })
我首先想到的是,一个联合类型在这里很有用。我已经看到了迈克尔萨宾用库里霍华德推导出的联盟类型,所以如果第一次预感是真的,那么我似乎有解决问题所需的基本机制。
但是:即使union类型是答案,如果我可以引用“从完全curried类型的函数到curried函数类型的所有类型的联合,并提供除最后一个参数以外的所有类型”。换句话说,一个办法把类型:
T1 => ... => Tn
到联合类型:
(T1 => ... => Tn) |∨| ... |∨| (Tn-1 => Tn)
将是作为用于上述g
类型是有用的。
否则在List
foldLeft
一个限制的讨论情况下T1
通过Tn-1
都是相同的。类似
(T1 =>)+ Tn
将描述我想为g
提供的类型。
我问不需要任意长链的具体情况,所以我们可以使用
(T1 =>){1,4} Tn
在想对于不是类型链做到这一点展望未来提供的迭代器范围平等的,但是,也许在某些类型的神奇功能是砍下了链到集合中的所有后缀是比较有用的:
Suffixes(T1 => ... => Tn)
实现这个远远超出目前我的斯卡拉能力。值得赞赏的是如何去做这些事情的提示。这是否可以通过Scala的现有类型系统的高级用法或通过编译器插件来完成,或者我都不知道。
如以下注释中所述,将结果称为“联合类型”不适合此用例。我不知道还有什么可以称之为的,但这是我目前最接近的想法。其他语言对这个想法有特别的支持吗?这将如何在Coq和Agda工作?
对于我来说,命名这个问题并理解它的位置(类型理论,可判定性等等)对于我来说比对ANSWER
的工作实现更重要,尽管两者都很好。奖金指向任何可以与Scalaz,Monoid或类别理论相关联的人。
我不知道那个工会类型是去这里的路。看起来好像你是在对一个HList表示的参数进行curried函数的折叠式的事情之后。我认为那样的事情可能是可行的。无论如何,这是一个有趣的问题......如果我提出任何可行的方案,我会进行调查和回答。 –
哇 - 谢谢,Miles。我很想听听你对这个问题的看法。我同意工会类型本身似乎并不完全是这种情况下所要求的。 –
@MilesSabin我已经澄清了我的问题并提出了一些可能需要回答的表单。我还不清楚这是否应该成为可能,但无论哪种方式,这对我来说都是一个很好的练习。 –